简单介绍
目前很多的教程中都会有讲到requests
,但它们通常从整个爬虫的原理讲起,讲到这部分知识时更多的注重于呈现运行结果。这里我将结合自身的使用做一个简单总结,对需要特别注意的点进行标注,代码很少,但其模式已经足够适用于大部分目标。
使用方法
基本用法(GET
)
GET
请求方式是最常用的方式:
import requests
url = "http://www.httpbin.org/ip"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36',
}
res = requests.get(url=url, headers=headers)
print(res.text) # 得到响应的文本格式(unicode),用res.content可以获取二进制文件如图片
基本用法(POST
)
POST
方式常用在登陆及json获取时:
import requests
url = "http://www.httpbin.org/post"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36',
}
data = { # 构造data数据
'user': 'test_name',
'passwd': 'test_passwd'
}
res = requests.post(url=url, headers=headers, data=data)
print(res.text)
基本的用法如上所示,十分简单,唯一值得注意的是headers
,绝大多数网站会检测请求头,这基本上是爬虫的第一道关卡。通常仅设置一个User-Agent
就可以访问一些简单的站点,但是更多的网站可能会借助其它字段进行一个人机判断。常见的请求头格式如下:
headers = {
"Accept": "application/json",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "zh-CN,zh;q=0.9",
"Connection": "close",
"Content-Length": "0",
"Cookie": "_gauges_unique_year=1; _gauges_unique=1; _gauges_unique_hour=1; _gauges_unique_day=1; _gauges_unique_month=1",
"Host": "www.httpbin.org",
"Origin": "http://www.httpbin.org",
"Referer": "http://www.httpbin.org/",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36"
}
关于请求头的设置,建议是从浏览器全部复制(对于新手一定是宁多勿少,也有例外,如编码,后面会将),除非你能明确其中一部分是对身份判断无关的,而这通常是试出来的,具有被封禁的危险,特别是对应内容分发服务器地址时尤为注意。
乱码的解决思路
方法1:
# 查看`headers`中是否设置:
'accept-encoding': 'gzip, deflate, br',
# 如果有,修改为:
'accept-encoding': 'gzip',
方法2:
安装brotlipy,依照文档使用。
原因为你同意了该种压缩方式后,有的服务器便采用了br
这种压缩方法。
当然如果还是乱码,可以从编码方面下手做解决思路,此处不做论述。只是建议首先尝试上述的方式,这通常已经能解决问题了。
Cookies
的使用
cookies
参数配合字典:
cookies = dict('test_token': '_123456')
res = requests.get(url=url, headers=headers, cookies=cookies)
cookies
参数配合RequestCookiesJar
:
cookies_jar = requests.cookies.RequestsCookieJar()
cookies_jar = cookies_jar.set('test_token', '_123456', domain='httpbin.org', path='/')
res = requests.get(url, headers=headers, cookies=cookies_jar)
代理的使用
proxies = {
'http': '134.xxx.xxx.xxx:xxx' # 代理iP的ip地址
}
res = requests.get(url=url, headers=headers, cookies=cookies, proxies=proxies)
如果需要使用代理,这里需要设置代理IP
,对代理池有兴趣可以参考我的另一篇文章:利用Python建立和维护爬虫代理IP池,或直接在我的github
上查看代理池源码,此处不展开。
超时设置
这一点我想重点强调,因为这是很容易忽视的一个问题,特别是当你还没有遇到这个问题时。
先说设置,设置很简单,如下:
res = requests.get(url=url, headers=headers, cookies=cookies, proxies=proxies, timeout=5) # 连接和读取超时均设置为5s
res = requests.get(url=url, headers=headers, cookies=cookies, proxies=proxies, timeout=(3, 5)) # 连接超时3s,读取超时5s
再说原因,requests
默认参数是无限等待,如果你没有超时检测机制(事实上好多教程也没有提),那么当你得意洋洋的让你的爬虫在服务器上跑了几小时几天,然后打开一看的结果,很有可能是:停了!
这个小细节很重要,请务必记住。但是我也不明白它为什么在文档的最后…
Session
的使用
这里先说两个典型的场景:
- 账号登入后维持
cookies
,达到复用的效果。 - 同一个网站为了防止账号被封,同时登入多个账号有序抓取。
Session
便是解决这些问题的,它会在同一个实例发出的所有请求之间保持cookie
。配置如下:
import requests
url = "http://www.httpbin.org/ip"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36',
}
cookies = { # 实际使用中建议敏感信息放置在不共享的配置文件中,通过导入读取
'user': 'xxx',
'auth': 'xxx',
}
s = requests.session() # 创建session
requests.utils.add_dict_to_cookiejar(s.cookies, cookeis) # 为session添加cookies
res = s.get(url=url, headers=headers, timeout=60) # 通过session访问链接
print(res.text)
注意实际环境中,关于账号的cookies
很可能是通过post
方法请求某个页面(如登陆页)得到的,而不是提前就准备好的。因为cookie
通常具有时效性,我们常用的方式是在一定的时间周期内请求更新一次,避免失效。
下面是通过访问页面获取cookies
结合session
的代码演示:
"""仅作示范提供思路,login_url并未配置,配置后参数也需要根据实际修改"""
import requests
def get_cookies(username, passwd):
"""从登陆页获取cookeis_jar"""
login_url = "" # 登陆链接
headers = {} # 登陆页的请求头
login_data = { # 登陆post data
'username': 'test_name',
'password': 'test_password',
}
res = requests.post(url=login_url, headers=headers, data=data)
ck_jar = res.cookies # 获取返回的cookies_jar
return ck_jar
def edit_cookies(cookiejar):
"""编辑cookiejar,构造需要的cookie"""
ck_dict = requests.utils.dict_from_cookiejar(ck_jar) # 转换为字典
cookies = {
"name": ck_dict['name'],
"auth": ck_dict['auth'], # 提取出name和auth组成一个新cookies
}
return cookies
def gen_session(cookies):
"""构造session"""
s = requests.session()
requests.utils.add_dict_to_cookiejar(s.cookies, cookeis) # 配置session的cookeis参数
return s
if __name__ == "__main__":
url = "http://www.httpbin.org/cookies"
headers = { # 内容页的请求头(此处为方便理解设置为一样,实际不同的页面中可能不同)
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36',
}
s1 = gen_session(edit_cookies(get_cookies(username="user1", password="123"))) # 构造session1
s1 = gen_session(edit_cookies(get_cookies(username="user2", password="456"))) # 构造session2
s1.get(url=url, headers=headers, timeout=60) # 账号1访问url
s2.get(url=url, headers=headers, timeout=60) # 账号2访问url
print(s1.cookies)
print(s2.cookies)
其它
- 通过检测返回状态码,可以判断是否访问成功,增加相应的容错
- 建议把
requests
访问部分封装成一个函数或类方法,在里面增加错误捕捉,错误时休眠及循环访问的功能,一劳永逸。
总结
以上的几点已经涵盖我目前使用requests
的大部分场景了,对于其它一些的需求都是特定场景下才需要了,在文档中均有涵盖,建议大家收藏Requests文档,遇到问题时可以直接查阅。