Python爬虫教程

第一章: 初学乍练-Python快速入门

第二章: 初窥门径-从全局把握网络爬虫

第三章: 爬虫数据-网页与JSON

第四章: 爬虫核心-HTTP协议

第五章: 手到擒来-数据的抓包

第六章: 利刃出鞘-HTTP请求库

第七章: 尘埃落定-数据的解析

第八章: 逆向初探-JS逆向

第九章: 爬虫进阶-Selenium, 中间人拦截

第十章:斗转星移-常用的反爬策略及应对方法

首页 > Python爬虫教程 > 第六章: 利刃出鞘-HTTP请求库 > 6.3节: 高效的HTTP请求库:requests

6.3节: 高效的HTTP请求库:requests

薯条老师 2021-03-08 10:20:11 236120 0

编辑 收藏

广州番禺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,免费领取课程大纲

扫码免费领取学习资料:


欢迎 发表评论: