爬虫库Requests
Requests是Python的一个很实用的HTTP客户端库,完全满足如今网络爬虫的需求。与Urllib对比,Requests不仅具备Urllib的全部功能;在开发使用上,语法简单易懂,完全符合Python优雅、简洁的特性;在兼容性上,完全兼容Python 2和Python3,具有较强的适用性,操作更加人性化。
1.安装
Requests库作为python的第三方库,可以通过pip安装,如下所示:
- Windows:
pip install requests
。 - Linux:
sudo pip install requests
。
除了使用pip安装之外,还可以下载whl文件安装,不过步骤较为复杂,这里就不多做介绍。
值得一提的是Requests是一个开源库,源码位于GitHub:https://github.com/kennethreitz/requests,大家如果想下载最新版本,可以直接到GitHub上下载Requests的源代码,下载链接为:https://github.com/kennethreitz/requests/releases。将源代码压缩包进行解压,然后进入解压后的文件夹,运行setup.py文件即可。
2.发送请求
HTTP的常用请求是GET和POST, Requests对此区分两种不同的请求方式。
import requests
url = 'https://baidu.com/'
# GET请求
r = requests.get(url, params=params, headers=headers, proxies=proxies, verify=True, cookies=cookies)
# POST请求
r = requests.post(url, data=data, files=files,headers=headers, proxies=proxies, verify=True, cookies=cookies)
GET请求
GET请求有两种形式,分别是不带参数和带参数,例如:
# 不带参数
https://www.baidu.com/
# 带参数wd
https://www.baidu.com/s?wd=python
判断URL是否带有参数,可以对==符号“?”==判断。一般网址末端(域名)带有“?”,就说明该URL是带有请求参数的,反之则不带有参数。GET参数说明如下:
- wd是参数名,参数名由网站(服务器)规定。
- python是参数值,可由用户自行设置。
- 如果一个URL有多个参数,参数之间用“&”连接。
Requests实现GET请求,对于带参数的URL有两种请求方式:
import requests
# 第一种方式
r = requests.get('https://www.baidu.com/s?wd=python')
# 第二种方式
url = 'https://www.baidu.com/s'
params = {'wd':'python'}
r = requests.get(url, params=params)
# 输出生成的URL
print(r.url)
两种方式都是可以的,第二种方式是通过字典的形式传入参数和参数值,效果等同,在实际开发中建议使用第一种方式,因为代码简洁,如果参数是动态变化的,那么可使用字符串格式化对URL动态设置, 例如:'https://www.baidu.com/s?wd=%s' %('python')
。
POST请求
POST请求是我们常说的提交表单,表单的数据内容就是POST的请求参数。**Requests实现POST请求需设置请求参数data,数据格式可以为字典、元组、列表和JSON格式,**不同的数据格式有不同的优势。
# 字典类型
data = {'key1':'value1', 'key2':'value2'}
# 元组或列表
(('key1', 'value1'), ('key2', 'value2'))
# JSON
import json
data = {'key1':'value1', 'key2':'value2'}
# 将字典转换JSON
data = json.dumps(data)
# 发送POST请求
import requests
r = requests.post("https://www.baidu.com/", data=data)
print(r.text)
复杂的请求方式
复杂的请求方式通常有请求头、代理IP、证书验证和Cookies等功能。Requests将这一系列复杂的请求做了简化,将这些功能在发送请求中以参数的形式传递并作用到请求中。
(1)添加请求头:请求头以字典的形式生成,然后发送请求中设置的headers参数,指向已定义的请求头。
headers = {
'User-Agent':'......',
'...':'...',
......
}
requests.get("https://www.baidu.com/", headers=headers)
添加请求头headers是解决requests请求反爬的方法之一,相当于我们进去这个网页的服务器本身,假装自己本身在爬取数据。解决了在请求网页爬取的时候,输出的text信息中会出现抱歉,无法访问等字眼的问题。
(2)使用代理IP:代理IP的使用方法与请求头的使用方法一致,设置proxies参数即可。
import requests
proxies = {
"http":"http://10.10.1.10:3128",
"https":"http://10.10.1.10:1080",
}
requests.get("https://www.baidu.com/", proxies=proxies)
由于我们使用python爬虫在网站爬取东西,一个固定IP的访问频率就会很高,这不符合人为操作的标准,因为人操作不可能在几ms内,进行如此频繁的访问。所以一些网站会设置一个IP访问频率的阈值,如果一个IP访问频率超过这个阈值,说明这个不是人在访问,而是一个爬虫程序。那么我们的IP就可能被封,而且自己的IP也可能被查找出来,这时我们就可以使用一些高匿代理IP来满足我们更大的需要。
(3)证书验证:通常设置关闭验证即可。在请求设置参数verify=False时就能关闭证书的验证,默认情况下是True。如果需要设置证书文件,那么可以设置参数verify值为证书路径。
一般的网页都有认证证书,所以一般requests请求时不添加这个参数,但是仍有可能访问的网页没有认证证书,这时就可以关闭证书验证。不过关闭验证运行程序会爆红,但是仍能正常运行,没有影响
(4)超时设置:发送请求后,由于网络、服务器等因素,请求到获得响应会有一个时间差。如果不想程序等待时间过长或者延长等待时间,可以设定timeout的等待秒数,超过这个时间之后停止等待响应。如果服务器在timeout秒内没有应答,将会引发一个异常。
requests.get('https://www.baidu.com', timeout = 5)
requests.post('https://www.baidu.com', timeout = 5)
(5)设置Cookies:在请求过程中使用Cookies也只需设置参数Cookies即可。Cookies的作用是标识用户身份,在Requests中以字典或RequestsCookieJar对象作为参数。获取方式主要是从浏览器读取和程序运行所产生。
import requests
test_cookies = 'JSESSIONID=2C30FCABDBF3B92E358E3D4FCB69C95B; Max-Age=172800;'
cookies = {}
# 分割,将字符串转换成字典格式
for i in test_cookies.split(';'):
value = i.split('=')
cookies[value[0]] = value[1]
r = requests.get(url, cookies=cookies)
print(r.text)
当程序发送请求时(不设参数cookies),会自动生成一个RequestsCookieJar对象,该对象用于存放Cookies信息。
import requests
url = 'https://www.baidu.com/'
r = requests.get(url)
# r.cookies是RequestsCookieJar对象
print(r.cookies)
thecookies = r.cookies
# RequestsCookieJar转换为字典
cookie_dict = requests.utils.dict_from_cookiejar(thecookies)
print(cookie_dict)
# 字典转换RequestsCookieJar
cookie_jar = requests.cookiejar_from_dict(cookie_dict, cookiejar=None, overwrite=True)
print(cookie_jar)
# 在RequestsCookieJar对象中添加Cookies字典
print(requests.utils.add_dict_to_cookiejar(thecookies, cookie_dict))
3.获取响应
当向网站(服务器)发送请求时,网站会返回相应的响应(response)对象,包含服务器响应的信息。Requests提供以下方法获取响应内容。
- r.status_code:响应状态码。
- r.content:字节方式的响应体,需要进行解码。
- r.text:字符串方式的响应体,会自动根据响应头部的字符编码进行解码。
- r.raw:原始响应体,使用r.raw.read()读取。
- r.encoding:获取编码格式。
- r.headers:以字典对象存储服务器响应头,但是这个字典比较特殊,字典键不区分大小写,若键不存在,则返回None。
- r.json():Requests中内置的JSON解码器。
- r.raise_for_status():请求失败(非200响应),抛出异常。
- r.cookies:获取请求后的cookies。
- r.url:获取请求链接。
- r.history:将请求参数中的allow_redirects设置为True,允许重定向,可以通过r.history字段查看历史信息,即访问成功之前的所有请求跳转信息。
注意:在获得响应内容时可以使用r.text,但是有时会出现解码错误,获得乱码的情况,这是获得的编码格式不正确,可以通过r.encoding进行查看,也可以r.encoding = ‘…’ 来指定正确的编码格式,一般网页的编码为utf-8(也有可能是gbk)。
但是这种手动的方式略显笨拙,下面提供一种更加简便的方式:chardet,这是一个很好的字符串/文件编码检测模块。
首先安装模块:pip install chardet
安装完成后,使用chardet.detect()返回字典,其中confidence是检测精确度,encoding是编码形式。
import requests
r = requests.get('http://www.baidu.com')
print(chardet.detect(r.content))
# 将chardet探测到的编码赋给r.encoding实现解码
r.encoding = chardet.detect(r.content)['encoding']
print(r.text)