Python爬虫-request模块
目录
理论储备
爬虫原理通俗来说就是模拟人的操作来访问网页并抓取数据,其优势是效率远远超过人手
多数情况下,上述的操作都是基于HTTP协议完成的
HTTP四大特性:
- 基于应用层的协议
- 基于请求-响应模式,由客户端发起请求并等待服务端返回响应的模式
- 无状态保存,不会保存客户端信息
- 无连接,每次请求都需建立连接和断开连接
HTTP请求
- 请求首行:
- 请求首行指的是在发送HTTP请求时的第一行
- 包括
- 请求方法(GET、POST等)
- 请求URI(Uniform Resource Identifier)。
- 请求头:
- 请求头包含了关于请求的附加信息,以键值对的形式表示。
- 常见的请求头
- Content-Type
- User-Agent
- Cookie等
- 它们用来描述请求的相关属性和数据。
- 请求体:
- 请求体可选,通常用于POST请求,在请求体中携带参数和数据。
- 请求体的格式可以是
- urlencode形式的键值对
- JSON格式
- formdata格式
HTTP响应
- 响应首行:
- 响应首行指的是服务器返回响应时的第一行
- 其中包含了状态码,表示服务器对请求的处理结果
- 常见的状态码有200(成功)、301(永久重定向)、302(临时重定向)等
- 响应头:
- 响应头包含了关于响应的附加信息,以键值对的形式表示
- 常见的响应头有Set-Cookie、Cache-Control等,它们用来描述响应的相关属性和数据
- 响应体:
- 响应体是服务器返回给客户端的实际数据
- 它可以是HTML格式的网页内容,也可以是JSON格式的数据等
Request使用
导入
import requests
发送请求
# 导入模块
import requests
# 定义请求地址
url = "https://www.baidu.com/"
# 发送请求获取响应数据
response = requests.get(url)
# 返回状态码200表示访问成功
#<Response [200]>
一些常用的属性和方法包括:
response.status_code
: 响应的状态码,例如200表示请求成功,404表示页面不存在等response.text
: 响应的内容,通常是服务器返回的HTML文本response.json()
: 将响应的内容解析为JSON格式
请求
发送GET请求
携带params参数
# 发送带有参数的GET请求
url = "http://example.com/api/data"
params = {
'param1': 'value1',
'param2': 'value2'
}
response = requests.get(url, params=params)
携带请求头
- 常见的HTTP头部字段包括:
- Host:指定目标服务器的域名或IP地址。
- User-Agent:标识发送请求的用户代理(通常是浏览器)。
- PC浏览器
- APP浏览器
- Linux
- macOS
- Accept:指定客户端能够接收的内容类型。
- Content-Type:指定请求或响应中实体的媒体类型。
- Content-Length:指定实体主体的长度(以字节为单位)。
- Cookie:向服务器传递保存在客户端的cookie信息。
- Cache-Control:指定如何缓存和重新验证响应。
- Referer:大型网站通常都会根据该参数判断请求的来源
示例:
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36',
}
respone = requests.get('https://www.zhihu.com/explore',
headers=headers)
print(respone.status_code) # 200
生成随机User-Agent
from fake_useragent import UserAgent
headers = {
"User-Agent": UserAgent().random,
}
发送POST请求
POST请求特点:
- 数据不会出现在地址栏
- 数据大小没有限制
- 通常需要携带请求体
- 请求体中如果存在中文会使用URL编码
# 导入requests模块
import requests
# 伪装请求头
from fake_useragent import UserAgent
# 定义目标路由地址
tag_url = "http://www.aa7a.cn/user.php"
# 定义请求头参数
headers = {
'User-Agent': UserAgent().random,
'Referer': 'http://www.aa7a.cn/user.php?&ref=http%3A%2F%2Fwww.aa7a.cn',
# 通过尝试,只携带上面的参数即可
# 'Host': 'www.aa7a.cn',
# 'Origin': 'http://www.aa7a.cn',
}
# 定义请求体数据
data = {
'username': 'username',
'password': 'password',
'captcha': 'captcha',
'remember': 1,
'ref': 'http://www.aa7a.cn',
'act': 'act_login'
}
# 对目标地址发起请求
response = requests.post(url=tag_url, data=data, headers=headers)
# 打印响应数据
print(response.text)
Session对象
session会自动携带cookie
不使用session
headers = {
"User-Agent": UserAgent().random,
}
tag_url = "https://xueqiu.com/"
# 发起请求获取响应对象
response = requests.get(url=tag_url, headers=headers)
# 获取Cookie参数
cookie_params = dict(response.cookies)
# 定义需要cookie的目标网址
tag_url = "https://stock.xueqiu.com/v5/stock/batch/quote.json?symbol=SH000001,SZ399001,SZ399006,SH000688,SH000016,SH000300,BJ899050,HKHSI,HKHSCEI,HKHSTECH,.DJI,.IXIC,.INX"
response = requests.get(url=tag_url, headers=headers, cookies=cookie_params)
使用session
headers = {
"User-Agent": UserAgent().random,
}
# 创建 session 对象
session = requests.Session()
# 定义目标地址
tag_url = "https://xueqiu.com/"
# 发起请求获取响应对象
response = session.get(url=tag_url, headers=headers)
# 获取Cookie参数
cookie_params = dict(response.cookies)
# 定义需要cookie的目标网址
tag_url = "https://stock.xueqiu.com/v5/stock/batch/quote.json?symbol=SH000001,SZ399001,SZ399006,SH000688,SH000016,SH000300,BJ899050,HKHSI,HKHSCEI,HKHSTECH,.DJI,.IXIC,.INX"
# 不用手动携带 cookie 即可获取指定的数据
response = session.get(url=tag_url, headers=headers)
发送文件
import requests
files = {'file': open('a.jpg', 'rb')}
response = requests.post('http://httpbin.org/post', files=files)
print(response.status_code)
响应
响应数据类型
既然有发送请求那么一定也会从服务器接受响应
响应数据一般分为两种数据类型
字符串
import requests
response = requests.get('https://pic.netbian.com/uploads/allimg/240322/232300-171112098057a5.jpg')
# `response.text`: 将响应体转换为字符串形式。
data = response.text
print(data, type(data))
二进制
import requests
response = requests.get('https://pic.netbian.com/uploads/allimg/240322/232300-171112098057a5.jpg')
# `response.content`: 获取响应体的二进制内容,适用于处理图像、视频等非文本类型的响应。(默认是16进制)
data = response.content
print(data, type(data))
# 很多数据,但是是二进制类型的
响应状态码
import requests
response = requests.get('https://www.baidu.com/')
# `response.status_code`: 获取响应的状态码。
print(response.status_code)
# 200
响应头
import requests
response = requests.get('https://www.baidu.com/')
# `response.headers`: 获取响应头信息,返回一个字典对象。
print(response.headers)
# {'Cache-Control': 'private, no-cache, no-store, proxy-revalidate, no-transform', 'Connection': 'keep-alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Date': 'Fri, 22 Mar 2024 07:14:04 GMT', 'Last-Modified': 'Mon, 23 Jan 2017 13:23:55 GMT', 'Pragma': 'no-cache', 'Server': 'bfe/1.0.8.18', 'Set-Cookie': 'BDORZ=27315; max-age=86400; domain=.baidu.com; path=/', 'Transfer-Encoding': 'chunked'}
响应Cookie
import requests
response = requests.get('https://www.baidu.com/')
# 获取服务器返回的cookie信息。
print(response.cookies)
# <RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>
# 将cookie信息转换为字典形式。
print(response.cookies.get_dict())
# {'BDORZ': '27315'}
# 获取cookie信息并以列表形式返回
print(response.cookies.items())
# [('BDORZ', '27315')]
当前请求/响应对象的URL
两者的区别
- 没有重定向
- 两者通常是一致的。
- 有重定向
response.url
是重定向后的最终URLresponse.request.url
则是最初的请求URL
# 获取当前请求的URL
print(response.url)
# 获取响应对象的URL
print(response.request.url)
写入二进制数据
# 导入requests库
import requests
# 定义目标地址:该地址是一张图片,图片属于二进制数据
tag_url = "https://pic.netbian.com/uploads/allimg/240322/232300-171112098057a5.jpg"
# 向目标地址发起请求
response = requests.get(tag_url)
# 打开本地的文件路径,写入二进制数据必须用 wb 模式
file_path = "./a.jpg"
with open(file_path, 'wb') as f:
# 循环获取响应数据中的二进制数据,每次只获取 1024 个字节
for chunk in response.iter_content(chunk_size=1024):
# 如果存在数据,则进行文件数据的写入
if chunk:
f.write(chunk)
SSL认证
verify=False
关闭证书验证
response = requests.get(url=url, verify=False)
代理
当使用爬虫一次性发送过多请求时,如果对方此时将我们IP限制,那么本机就无法再访问该网站,解决的办法就是使用代理,通俗来说就是换个IP访问
配置代理
proxies参数设置全局代理
proxies={"协议":"协议://IP:端口号"}
示例:
import requests
proxies = {
'http': 'http://proxy.example.com:8080',
'https': 'https://proxy.example.com:8080'
}
response = requests.get(url, proxies=proxies)
超时设置
response = requests.get(url, timeout=5).text
如果请求超时时间超过了5秒,会抛出一个timeout异常
超时重试
def gethtml(url):
i = 0
while i < 3:
try:
html = requests.get(url, timeout=5).text
return html
except requests.exceptions.RequestException:
i += 1