知识点:
掌握headers参数的使用;
掌握 发送带参数的请求;
掌握 headers中携带cookie;
掌握 cookies参数的使用;
掌握 cookieJar的转换方法;
掌握 超时参数timeout的使用;
掌握 代理ip参数proxies的使用;
掌握 使用verify参数忽略CA证书;
掌握 requests模块发送post请求;
掌握 利用requests.session进行状态保持;
1、requests 模块介绍
发送http请求,获取响应数据
requests 模块发送get请求
1)、需求:通过requests向百度首页发送请求,获取该页面的源码;
2)、运行下面的代码,观察打印输出的结果;
import requests
url = 'https://www.baidu.com/'
response = requests.get(url)
#打印源码的str类型数据
print(response.text)
2、response响应对象
观察上边代码运行结果发现 有好多乱码,这是因为编解码使用的字符集不同造成的,我们尝试使用下边的办法来解决中文乱码问题。
import requests
url = 'https://www.baidu.com/'
response = requests.get(url)
# 手动设定编码格式
response.encoding = 'utf-8'
#打印源码的str类型数据
print(response.text)
print(response.encoding)
# response.content是存储的bytes类型的响应源码,可以进行decode操作
print(response.content.decode())
1)、responese.text是requests模块安装chardet 模块推测处理的编码字符集进行解码的结果。
2)、网络传输的字符串都是bytes类型的,所以response.text = response.content.decode(‘推测出的编码字符集’)
3)、我们可以在网页源码中搜索charset,尝试参考该编码字符集,注意存在不准确的情况;
2.1 response.text和response.content的区别:
response.text
类型:str;
解码类型:requests模块自动根据http头部响应的编码做出有根据的推测,推测的文本编码;
reponse.content
类型:bytes
解码类型:没有指定;
2.2 通过对response.content进行decode,来解决中文乱码
response.content.decode() 默认utf-8;
response.content.decode(“G8K”)
常见的编码字符集
utf-8;
gbk;
gb2312;
ascii(读音:阿斯克码);
iso-8859-1;
2.3 response 响应对象的其它常用属性或方法
response = requests.get(url) 中response是发射请求获取的响应对象:response响应对象中除了text、content获取响应内容以外还有其它常用的属性或方法:
response.url 响应的url,有时候响应的url和请求的url并不一致;
response.status_code 响应状态码;
response.requests.headers 响应对应的请求头;
response.request_cookies 响应对象请求cookie;返回cookieJar类型
response.cookies 响应的cookie(经过 set-cookie动作;返回cookieJar类型)
response.json() 自动讲json字符串类型的响应内容转换为Python对象(dict or list)
import requests
url = 'https://www.baidu.com/'
response = requests.get(url)
# # 手动设定编码格式
# response.encoding = 'utf-8'
#
# #打印源码的str类型数据
# print(response.text)
#
# print(response.encoding)
#
# # response.content是存储的bytes类型的响应源码,可以进行decode操作
# print(response.content.decode())
# 常见的响应对象参数和方法
# 响应url
print(response.url)
# 状态码
print(response.status_code)
# 响应对应的请求头
print(response.request.headers)
# 响应头
print(response.headers)
# 答应响应设置cookies
print(response.cookies)
3、requests模块发送请求
3.1 发送带header的请求
我们先写一个获取百度首页的代码
import requests
url = 'https://www.baidu.com/'
response = requests.get(url)
print(len(response.content.decode()))
print(response.content.decode())
# 构建请求头字典
headers ={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36'
}
# 发送请求头的请求
response1 = requests.get(url,headers = headers)
print(len(response1.content.decode()))
print(response1.content.decode())
3.2 发送带参数的请求
我们在使用百度搜索的时候经常发现url地址中会与一个 ?,那么该问号后边的就是请求参数,又叫做查询字符串。
3.2.1 在url携带参数
直接对参数的url发起请求
import requests
url = 'https://www.baidu.com/'
respose = requests.get(url)
print(len(respose.content.decode()))
print(respose.content.decode())
# 构造请求头字典
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36'
}
respose = requests.get(url,headers=headers)
with open('baidu.html','wb') as f:
f.write(respose.content)
3.2.2 通过params携带参数字典
1)、构建请求参数字典;
2)、向接口发送请求的时候带上参数字典,参数字典设置给params;
import requests
url = 'https://www.baidu.com/s?wd=python'
headers = {
"User-Agent":'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36'
}
# 构建参数字典
data = {
'wd':'python'
}
reponse = requests.get(url,headers=headers,params=data)
print(reponse.url)
with open('baidu1.html','wb') as f:
f.write(reponse.content)
3.3 在headers参数中携带cookie
网站经常利用请求头中的Cookie字段来做用户访问状态的保持,那么我们可以在headers参数中添加Cookie,模拟普通用户的请求,我们一github登陆为例:
3.3.1 github登陆抓包分析
1)、打开浏览器,右键-检查,点击Net Work,勾选Preserve log;
2)、访问github登陆的url地址,https://github.com/
3)、输入账号密码点击登陆后,访问一个需要登陆后才能获取正确内容的url,比如点击右上角的Your profile 访问https://github.com/USER_NAME
4)、确定url之后,再确定发送该请求所需要的请求头信息中的User-Agent和Cookie;
3.4 cookies参数的使用
1、cookies参数的形式 :字典
cookies = {“cookie的name”:"cookie的value”}
该字典对应请求头中cookie字符串,以分号、空格分割每一对字典兼职对;
等号左边的是一个cookie的name,对应cookies字典的key;
等号右边对应的cookies字典的value;
2、cookies参数的使用方法
response = requests.get(url,cookies)
3、将cookie字符串转换为cookies参数所需的字典;
cookies_dict = {cookie.split('=')[-1] for cookie in cookies_str.split(';')}
4、cookie一般有过期时间的,一旦过期需要重新获取;
3.4 cookieJar对象转换为cookies字典方法
使用request获取的response对象,具有cookies属性,该属性值是一个cookieJar类型,包含了对方服务器设置在本地的cookie,我们如何将其转换为cookies字典呢?
1)、转换方法
cookies_dict = requests.utils.dict_from_cookiejar(response.cookies)
2)、其中response.cookies返回的就是cookieJar类型的对象;
3)、requests.utils.dict_from_cookiejar 函数返回cookies字典;
import requests
url = 'http://www.baidu.com'
response = requests.get(url)
print(response.cookies)
dict_cookies = requests.utils.dict_from_cookiejar(response.cookies)
print(dict_cookies)
jar_cookies = requests.utils.cookiejar_from_dict(dict_cookies)
print(jar_cookies)
3.5 超时参数timeout的使用
在平时网上冲浪的过程中,我们经常会遇到网络波动,这个时候,一个请求等了很久可能任然没有结果。
在爬虫中,一个请求很久没有结果,就会让整个项目的效率变得非常低,这个时候我们就需要对请求进行强制要求,让他必须在特定的视觉内返回结果,否则就报错。
1、超时参数timeout的使用方法
response = requests.get(url,timeout=3)
2、timeout=3表示:发送请求后,3秒钟内返回响应,否则就抛出异常
import requests
url = ''
# 设置超时
response = requests.get(url,timeout=3)
3.6 理解使用代理的过程
3.6.1 理解代理的过程
1、代理IP是一个IP,指向的是一个代理服务器;
2、代理服务器能够帮我们向目标服务器转发请求;
3…6.2 正向代理和反向代理的区别
前边提到proxy参数指定的代理ip指向的是正向代理服务器,那么相应的就有反向服务器;现在来了解一下正向代理服务器和反向代理服务器的区别;
1)、从发送请求的角度,来区分整型或反向代理;
2)、为浏览器或客户端(发送请求的一方)转发请求的,叫做正向代理;
浏览器指定最终处理请求的服务器的真实ip地址,例如VPN;
3)、不为浏览器或客户端(发送请求的一方)转发请求、而是为最终处理请求的服务器转发请求的,叫做反向代理。
浏览器不知道服务器的真实地址,例如nginx。
3.6.3 代理ip(代理服务器)的分类
1、根据dialip的匿名程度,代理ip可以分为下面三类:
1)透明代理(Transparent Proxy):透明代理虽然可以治具“隐藏”你的IP地址,但是还是可以查到你是谁。目标服务器接收到的请求头如下:
REMDTE_ADDR = Proxy IP
HTTP_VIA = Proxy IP
HTTP_X_FORWARDED_FOR = Your IP
2)匿名代理(Anonymous Proxy):使用匿名代理,别人只能指定你用了代理,无法指定你是谁。目标服务器接收到的请求头如下:
REMDTE_ADDR = proxy_IP
HTTP_VIA = proxy IP
HTTP_X_FORWARDED_FOR = proxy IP
REMDTE_ADDR = Proxy IP
HTTP_VIA = not determined
HTTP_X_FORWARDED_FOR = not determined
2、根据网站所使用的协议不同,需要使用响应协议的代理服务。从代理服务请求使用的协议可以分为:
http代理:目标url为http协议;
https代理:目标url为https协议;
socks隧道代理(lirsocks5代理)等;
socks代理只是简单地址传递数据包,不关心是何种应用协议(FTP、HTTP和HTTPS等)。
socks代理比http、https代理耗时少;
socks 代理可以转发http和https的请求;
3.6.4 proxies代理参数的使用
为了让服务器以为不是同一个客户端在请求:为了防止频繁向一个匿名发送请求被封IP,所以我们需要使用代理IP,那么我们接下来要学习requests模块是如何使用代理ip的。
用法:
response = requests.get(url,proxies=proxies)
proxies的形式:字典
注意:如果proxies字典中包含有多个键值对,发送请求时按照url地址的协议来选择使用相应的代理IP。
import requests
url = 'http://www.baidu.com'
proxies = {
'http':'http://218.95.81.51:9000',
'http':'http://218.95.81.51:9000'
}
response = requests.get(url,proxies = proxies)
print(response.text)
3.7 使用verify参数忽略CA证书
在使用浏览器上网的时候,有时能够看到下面的提示。“您的链接不是私密链接”。
原因:该王章的CA证书没有经过(受信任的根证书颁发机构)的认证。
3.7.1 运行代码长代码中向不安全的链接发起请求的效果
运行下面的代码家那个会抛出保护ssl.certificatError…字样的异常
import requests
url = ''
reponse = requests.get(url)
3.7.2 解决方案
为了在代码中能够正常的请求,我们使用 verifyFalse 参数,此时requests模块发送请求将不能做CA证书的验证,verify参数能够忽略CA证书的认证。
import requests
url = 'http://sam.huat.edu.cn:8443/selfservice'
reponse = requests.get(url,verify = False)
print(reponse.Content)
4、requests 模块发送post请求
思考:哪些地方我们会用到POST请求?
1、登录注册(在web工程师看来POST比GET更安全,url地址中不会暴露与用户的账号密码等信息)
2、需要传输大文本内容的时候(POST请求对数据涨肚没有需求)
所以同样的,我们的爬虫也需要在这两个地方回去模拟浏览器发送POST请求;
4.1 requests发送post请求的方法
resquests = requests.post(url,data)
data 参数接收一个字典
requests 模块发送post请求参数和发送get请求的参数完全一致。
4.2 POST请求练习
下面我们通过金山反应的例子看看post请求和如何使用
1、地址:https://www.iciba.com/
思路分析
1、抓包确定请求的url地址;
import requests
import json
import sys
class King(object):
def __init__(self):
self.url = "url = 'https://www.iciba.com/'ajax.php?a=fy"
self.headers ={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36'
}
self.data = {
"f":"auto",
"t":"auto",
"w":word
}
def get_data(self):
# 使用post方法发送一个post请求,data位请求体的字典
response = requests.post(self.url,data = self.data,headers = self.headers)
return response.content
def parse_data(self,data):
# loads 方法将json字符串转成python字典
dict_data = json.loads(data)
try:
print(dict_data['content']['out'])
except:
print(dict_data['content']['word_mean'][0])
def run(self):
#编写爬虫逻辑
#url
# headers
# data字典
# 发送请求获取响应
response = self.get_data()
print(response)
# 数据解析
self.parse_data(response)
if __name__ == '__main__':
word = input('请输入要翻译的单词或者句子:')
#word = sys.argv[1]
King = King('word')
King.run()
quests模块发送post请求
1、实现方法:
requests.post(url,data)
data是一个字典
2、post数据来源
1.固定值 抓包比较不变值;
2.输入值 抓包比较根据自身变化值;
3.预设值 - 静态文件 需要提前从静态html中获取;
4.预设值-发请求 需要对地址发送请求
5.在客户端生产的;分析js,模拟生产数据;
5、利用requests.session进行状态保持
requests模块中Session类能够自动处理发送请求响应过程中产生的cookie,进而达到状态保持的目的。
5.1 requests.session的作用以及一个月场景
requests.session的作用
自动处理cookie,即 下一次请求会带上前一次的cookie;
requests.session的应用场景
自动处理连续的多次请求过程中产生的cookie;
5.2 requests.session使用方法
session 实例在请求一个网站后,对方服务器设置在本地的cookie会保存在session中,下一次再使用session请求对方服务器的时候,会带上前一次的cookie。
session = requests.session() #实例化 session 对象
response = session.get(url,headers,.....)
response = session.post(url,data,....)
session对象发送get或post请求的参数,与requests模块发送请求的参数完全一致。
5.3 课堂测试
使用requests.session来完成github登陆,并获取需要登陆后才能访问的页面。
5.3.1 提示
1、对GitHub登陆以及访问登陆后才能访问的页面的整个完成过程进行抓包;
2、确定登陆请求的url地址,请求方法和所需的请求参数;
部分请求参数在别的url对应的响应内容中,可以使用re模块获取;
3、确定登陆后才能访问的页面的url地址和请求方法;
4、利用requests.session完成代码;
import requests
def login():
# session
session = requests.session()
# headers
session.headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36'
}
# url1 -获取token
url1 = 'https://github.com/login'
# 发送请求响应
res_1 = session.get(url1).content.decode()
# 正则提取
token = requests.findall('name="authenticity_token" value="(.*?)"/>',res_1[0])
#' name="authenticity_token" value="Oqjjjda890EkevrJNNAkUwKGDB,QIIseAQyKGUUZebMTULb6HI7hWF5oP/KOmKzI2LoLvRijGlDw8IRFHAwXmjw==" />'
# url2 - 登陆
url2 = 'https://github.com/session'
# 构建表单数据
data ={
"commit":"Sign_in",
"utf8":"✓",
"authenticity_token":token,
"login":"exile-morganna",
"password":"1QAZ2wSX3edC4rfv",
"webauthn-support":"Supported",
}
print(data)
# 发送请求登陆
session.post(url2,data = data)
# url3 - 验证
url3 = 'https://github.com/exile-morganna'
response = session.get(url3)
with open('github.html','wb') as f:
f.write(response.content)
if __name__ == '__main__':
login()