广州番禺Python爬虫小班周末班培训
第四期线下Python爬虫小班周末班已经开课了,授课详情请点击:http://chipscoco.com/?id=232
6.3.1 requests官方警告
requests官方文档的中文版首页贴了一段很有意思的话:
非专业使用其他HTTP库会导致危险的副作用,包括:安全缺陷症、冗余代码症、重新发明轮子症、啃文档症、抑郁、头疼、甚至死亡。
薯条老师入行已十年有余,期间写过不少代码,也造过一些轮子。与大多数程序员一样,在学习的过程中亦有困惑:是自己从头实现一遍,还是直接用前人写好的框架?
重新发明轮子自有好处,比如提升代码能力,框架编写能力,全局的架构能力。缺点是费时费力,如有充足的时间或内心坚定,自可遵循己心,功成后将其开源。如目的仅是快速的进行应用开发,那么,还是直接用别人写好的,经过多次迭代、测试,已经成熟稳定的开源框架吧!
6.3.2 requests快速入门
(1) 安装requests
在2.3节的内容中已经讲解了requests的安装方法,直接在命令行中通过pip来进行安装:
pip install requests
(2) 快速发起HTTP请求
requests模块提供了与HTTP动词同名的方法,以快速发起HTTP请求:
请求方法 | 描述 |
requests.get(url,params=None, **kwargs) | HTTP协议中的GET请求 |
requests.post(url, data=None, json=None, **kwargs) | HTTP协议中的POST请求 |
requests.put(url, data=None, **kwargs) | HTTP协议中的PUT请求 |
requests.head(url, **kwargs) | HTTP协议中的HEAD请求 |
requests.options(url, **kwargs) | HTTP协议中的OPTIONS请求 |
方法中的第一个参数都为url, 表示请求的资源地址。get方法中的params参数用来传递url参数,post方法中的data以及json用来传递提交给服务端的数据。put方法,head方法,options方法中的参数使用方法与get, post是一样的,不再赘述。各请求方法的返回值是一个Response对象,下表为Response对象常用的属性和方法:
常用属性和方法 | 描述 |
url | 请求的url |
text | 从服务端响应的文本数据 |
content | 从服务端响应的字节流数据 |
json() | 调用该方法将响应的json数据反序列化 |
status_code | 服务端的响应状态码 |
reason | 与响应状态码对应的描述信息 |
cookies | 服务端响应的cookie信息,系RequestsCookieJar对象 |
headers | 服务端的响应头信息,字典类型 |
代码实例-抓取python官网首页:
import requests url = 'https://www.python.org/' r = requests.get(url) print(r.text)
如果需要在执行get方法时传递url参数,可以通过params参数。params参数接收一个字典对象,键名表示请求的参数名,键值表示传递的url参数。
代码实例-抓取python官方文档:
import requests # Python官方文档的查询url url = 'https://docs.python.org/3/search.html' # 在官方文档中抓取urllib的文档数据 payload = {'q': 'urllib'} r = requests.get(url, params=payload) # 可以输出url来查看完整的url print(r.url) # 输出为: https://docs.python.org/3/search.html?q=urllib # 输出抓取到的文档查询信息 print(r.text)
post方法用来提交数据给服务器,直接将字典类型的实参通过data进行传递,或者将json格式的数据通过json参数来进行传递。
代码实例-模拟登录chipscoco:
import requests # 以下为薯条老师博客的登录url login_url = 'http://chipscoco.com/zb_users/plugin/YtUser/cmd.php?act=verify' # 构造一个form data, username为登录的用户名,edtPassWord为加密后的登录密码 form_data = {"username":"test", "edtPassWord":"47ec2dd791e31e2ef2076caf64ed9b3d"} r = requests.post(login_url, data=form_data) # cookies是一个RequestsCookieJar对象 for item in r.cookies: print(item.name + '=' + item.value)
(3) 定制HTTP请求头
定制HTTP请求头需通过关键字参数headers进行传递。headers接收一个字典类型的参数,键名表示HTTP请求头的字段名,键值为请求字段所对应的字段值。
代码实例-为爬虫程序设置UA:
import requests # 以下url并不存在,读者可将其替换为真实的网页url url = 'http://www.justtest.com' # Chrome浏览器的UA user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.57' # 设置爬虫程序的UA,可在一定程度上防止被服务端反爬 headers = {'User-Agent': user_agent} r = requests.get(url, headers=headers)
(4) 获取与发送cookies
服务端的响应中如果包含cookie信息,可通过Response对象的cookies进行访问,代码实例详见上文中的“模拟登录chipscoco”。在爬虫程序的开发场景中,很多情况下需要发送cookie给服务端,以维持状态信息,此时可以通过RequestsCookieJar对象的set方法构造一个cookie:
set(self, name, value, **kwargs)
name表示字段名,value表示字段值,可以在关键字参数中使用domain来传递请求的域名,用path参数来指定请求的路径。代码实例-抓取chipscoco网页教程:
import requests # 以下为薯条老师博客的登录url login_url = 'http://chipscoco.com/zb_users/plugin/YtUser/cmd.php?act=verify' # 构造一个form data, username为登录的用户名,edtPassWord为加密后的登录密码 form_data = {"username":"test", "edtPassWord":"47ec2dd791e31e2ef2076caf64ed9b3d"} r = requests.post(login_url, data=form_data) jar = requests.cookies.RequestsCookieJar() # 主要是演示set方法的使用 for item in r.cookies: jar.set(item.name, item.value) # 待抓取的在线教程地址 page_url = 'http://www.chipscoco.com' payload = {'id': 9} # 通过关键字参数cookies来传递cookie r = requests.get(page_url, params=payload, cookies=jar) print(t.text)
6.3.3 requests进阶用法
(1) 保持cookie
在5.2.2节的代码实例中,如需保持某些请求头参数和cookie信息,需要每次发起请求时都显式地指定headers和cookies参数。通过requests中的Session对象,可以在同一个会话的所有请求间保持cookie。
构造Session对象时,通常使用with来进行上下文管理,并通过Session对象的get或post方法来发起请求。
代码实例-跨请求保持登录cookie:
import requests # 以下为薯条老师博客的登录url login_url = 'http://chipscoco.com/zb_users/plugin/YtUser/cmd.php?act=verify' page_url = 'http://chipscoco.com/?id=9' # 构造一个form data, username为登录的用户名,edtPassWord为加密后的登录密码 form_data = {"username":"test", "edtPassWord":"47ec2dd791e31e2ef2076caf64ed9b3d"} # 构造一个Session对象, 同一个会话的所有请求保持相同的cookie with requests.Session as s # 直接使用Session对象的post方法来发起请求 s.post(login_url, data=form_data) # get请求使用的是 发起post请求后服务端响应的cookie信息 s.get(page_url)
requests中的会话无法保持请求级别的参数,即后面的请求方法不能保持前面请求方法中的参数。
(2) PreparedRequest对象
在调用requests的get方法或post等方法时,requests在内部实现中会先构造一个Request对象,然后再通过Request的prepare方法构造一个PreparedRequest对象。
代码实例-直接构造PreparedRequest:
from requests import Request, Session # 以下为薯条老师博客的登录url login_url = 'http://chipscoco.com/zb_users/plugin/YtUser/cmd.php?act=verify' # 构造一个form data, username为登录的用户名,edtPassWord为加密后的登录密码 form_data = {"username":"test", "edtPassWord":"47ec2dd791e31e2ef2076caf64ed9b3d"} req = Request('POST', url = login_url, data=form_data) # 构造一个PreparedRequest对象 prepped = req.prepare() with requests.Session as s # 直接使用Session对象的send方法来发起请求 s.send(prepped)
直接构造PreparedRequest对象,以便在下文代码中对对象进行复用。其不足在于直接通过Request.prepare方法构造的是一个无状态的PreparedRequest对象,不会在会话中保持cookie。如需构造带状态的PreparedRequest,应当使用Session对象的prepare_request方法:
from requests import Request, Session # 以下为薯条老师博客的登录url login_url = 'http://chipscoco.com/zb_users/plugin/YtUser/cmd.php?act=verify' # 构造一个form data, username为登录的用户名,edtPassWord为加密后的登录密码 form_data = {"username":"test", "edtPassWord":"47ec2dd791e31e2ef2076caf64ed9b3d"} req = Request('POST', url = login_url, data=form_data) with requests.Session as s # 获取一个带有状态的PreparedRequest prepped = s.prepare_request(req) # 直接使用Session对象的send方法来发起请求 s.send(prepped)
(3) 证书验证
在默认情况下,requests中的请求方法会开启SSL验证。通过请求方法中的关键字参数verify可以对SSL证书验证进行控制:
verify参数值 | 描述 |
True | 默认值,表示对SSL证书进行验证 |
False | 忽略对SSL证书的验证 |
path_to_certfile | 指向CA证书的目录,该文件夹必须通过 OpenSSL 提供的 c_rehash工具处理 |
>>> requests.get('https://github.com', verify='/path/to/certfile')
对于客户端证书,通过关键字参数cert来进行指定。cert既可以是一个元组类型,也可以是一个指向单个文件(包含证书和密钥)的文件夹路径:
>>> requests.get('https://test.com', cert=('/path/client.cert', '/path/client.key'))
对于SSL证书和客户端证书,同样可以将其保持在会话中:
s = requests.Session()
s.verify = '/path/to/certfile'
# 该文件同时包含证书和密钥
s.cert = '/path/client.cert'
(4) 使用代理
我们在开发爬虫程序的时候,通常需要设置代理服务器,以隐藏IP地址 。通过关键字参数proxies可以设置代理服务器:
import requests proxies = { "http": "http://10.10.1.10:3128", "https": "http://10.10.1.10:1080", } # 通过关键字参数proxies来指定代理服务器 requests.get("http://data_to_be_request.com", proxies=proxies)
6.3.4 知识要点
(1) 通过requests中的Session来保持会话cookie。
(2) 在requests的请求方法中,通过关键字参数proxies来指定爬虫代理。
6.3.5 高薪就业班
(1) Python后端工程师高薪就业班,月薪10K-15K,免费领取课程大纲
(2) Python爬虫工程师高薪就业班,年薪十五万,免费领取课程大纲
(3) Java后端开发工程师高薪就业班,月薪10K-20K, 免费领取课程大纲
(4) Python大数据工程师就业班,月薪12K-25K,免费领取课程大纲
扫码免费领取学习资料: