zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Python requests 模块

Python模块 requests
2023-09-11 14:16:46 时间

知识点:
掌握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
  1. 高匿代理(Elte proxy或High Anonymity Proxy):高匿代理让别人根本无法发现你是在用代理,所以是最好的选择,毫无疑问使用高匿代理效果最好。目标服务器接收到请求头如下:
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()