requests模块

1、为什么要重点学习requests模块,而不是urllib

  • 企业中用的最多的就是requests

  • requests的底层实现就是urllib

  • requests在python2 和python3中通用,方法完全一样

  • requests简单易用

2、requests的作用与安装

作用:发送网络请求,返回响应数据

安装

pip install requests

如果安装速度慢的话可以改用国内的源进行下载安装

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple requests

3、requests模块发送简单的get请求、获取响应

需求:通过requests向百度首页发送请求,获取百度首页的数据

import requests

# 目标url
url = 'https://www.baidu.com'

# 向目标url发送get请求
response = requests.get(url)

# 打印响应内容
print(response.text)

response的常用属性:

  • response.text 响应体 str类型

  • response.encoding 从HTTP header中猜测的响应内容的编码方式

  • respones.content 响应体 bytes类型

  • response.status_code 响应状态码

  • response.request.headers 响应对应的请求头

  • response.headers 响应头

  • response.request.cookies 响应对应请求的cookie

  • response.cookies 响应的cookie(经过了set-cookie动作)

  • response.url 获取访问的url

  • response.json() 获取json数据 得到内容为字典 (如果接口响应体的格式是json格式时)

  • response.ok

    如果status_code小于200,response.ok返回True。

    如果status_code大于200,response.ok返回False。

思考:text是response的属性还是方法呢?

  • 一般来说名词,往往都是对象的属性,对应的动词是对象的方法

3.1 response.text 和response.content的区别

  • response.text

    • 类型:str

    • 如果希望获取的是字符串,使用此方法。
    • 解码类型: requests模块自动根据HTTP 头部对响应的编码作出有根据的推测,推测的文本编码

    • 如何修改编码方式:response.encoding="gbk/UTF-8"

  • response.content

    • 类型:bytes

    • 如果希望获取的是图片等二进制内容,使用此方法。
    • 解码类型: 没有指定

    • 如何修改编码方式:response.content.deocde("utf8")

获取网页源码的通用方式:

  1. response.content.decode()

  2. response.content.decode("UTF-8")

  3. response.text

以上三种方法从前往后尝试,能够100%的解决所有网页解码的问题

所以:更推荐使用response.content.deocde()的方式获取响应的html页面

3.2 练习:把网络上的图片保存到本地

我们来把www.baidu.com的图片保存到本地

思考:

  • 以什么方式打开文件

  • 保存什么格式的内容

分析:

import requests

# 图片的url
url = 'https://www.baidu.com/img/bd_logo1.png'

# 响应本身就是一个图片,并且是二进制类型
response = requests.get(url)

# print(response.content)

# 以二进制+写入的方式打开文件
with open('baidu.png', 'wb') as f:
    # 写入response.content bytes二进制类型
    f.write(response.content)

4、发送带header的请求

我们先写一个获取百度首页的代码

import requests

url = 'https://www.baidu.com'

response = requests.get(url)

print(response.content)

# 打印响应对应请求的请求头信息
print(response.request.headers)

4.1 思考

对比浏览器上百度首页的网页源码和代码中的百度首页的源码,有什么不同?

代码中的百度首页的源码非常少,为什么?

4.2 为什么请求需要带上header?

模拟浏览器,欺骗服务器,获取和浏览器一致的内容

4.3 header的形式:字典

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}

4.4 用法

requests.get(url, headers=headers)

4.5 完整的代码

import requests

url = 'https://www.baidu.com'

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}

# 在请求头中带上User-Agent,模拟浏览器发送请求
response = requests.get(url, headers=headers)

# print(response.content)

# 打印请求头信息
print(response.request.headers)

5、发送带参数的请求

我们在使用百度搜索的时候经常发现url地址中会有一个 ?,那么该问号后边的就是请求参数,又叫做查询字符串

5.1 什么叫做请求参数:

例1: http://www.webkaka.com/tutorial/server/2015/021013/

例2:https://www.baidu.com/s?wd=python&a=c

例1中没有请求参数!例2中?后边的就是请求参数

5.2 请求参数的形式:字典

kw = {'wd':'长城'}

5.3 请求参数的用法

requests.get(url,params=kw)

5.4 关于参数的注意点

在url地址中, 很多参数是没有用的,比如百度搜索的url地址,其中参数只有一个字段有用,其他的都可以删除 如何确定那些请求参数有用或者没用:挨个尝试! 对应的,在后续的爬虫中,越到很多参数的url地址,都可以尝试删除参数

5.5 两种方式:发送带参数的请求

  • https://www.baidu.com/s?wd=python发起请求可以使用requests.get(url, params=kw)的方式

    # 方式一:利用params参数发送带参数的请求
    import requests
    
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
    
    # 这是目标url
    # url = 'https://www.baidu.com/s?wd=python'
    
    # 最后有没有问号结果都一样
    url = 'https://www.baidu.com/s?'
    
    # 请求参数是一个字典 即wd=python
    kw = {'wd': 'python'}
    
    # 带上请求参数发起请求,获取响应
    response = requests.get(url, headers=headers, params=kw)
    
    # 当有多个请求参数时,requests接收的params参数为多个键值对的字典,比如 '?wd=python&a=c'-->{'wd': 'python', 'a': 'c'}
    
    print(response.content)
  • 也可以直接对https://www.baidu.com/s?wd=python完整的url直接发送请求,不使用params参数

    # 方式二:直接发送带参数的url的请求
    import requests
    
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
    
    url = 'https://www.baidu.com/s?wd=python'
    
    # kw = {'wd': 'python'}
    
    # url中包含了请求参数,所以此时无需params
    response = requests.get(url, headers=headers)

6、使用requests发送POST请求

思考:哪些地方我们会用到POST请求?

  1. 登录注册( POST 比 GET 更安全)

  2. 需要传输大文本内容的时候( POST 请求对数据长度没有要求)

所以同样的,我们的爬虫也需要在这两个地方回去模拟浏览器发送post请求

6.1 requests发送post请求语法:

  • 用法:

    response = requests.post("http://www.baidu.com/", data = data, headers=headers)
  • data 的形式:字典

6.2 POST请求练习

下面面我们通过金山翻译的例子看看post请求如何使用:

地址:https://www.iciba.com/fy

思路分析

1.抓包确定请求的url地址

2.确定请求的参数

3.确定返回数据的位置

 

4.模拟浏览器获取数据

import requests
import json

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}

url = 'https://ifanyi.iciba.com/index.php?c=trans&m=fy&client=6&auth_user=key_ciba&sign=99730f3bf66b2582'

data = {
    'from': 'zh',
    'to': 'en',
    'q': 'lucky 是一个帅气的老师'
}

res = requests.post(url, headers=headers, data=data)
# print(res.status_code)

# 返回的是json字符串 需要在进行转换为字典
data = json.loads(res.content.decode('UTF-8'))
# print(type(data))
print(data)
print(data['content']['out'])

7、requests中cookirJar的处理方法

使用request获取的resposne对象,具有cookies属性,能够获取对方服务器设置在本地的cookie,但是如何使用这些cookie呢?

7.1 方法介绍

  1. response.cookies是CookieJar类型

  2. 使用requests.utils.dict_from_cookiejar,能够实现把cookiejar对象转化为字典

7.2 方法展示

import requests
​
url = "http://www.baidu.com"
#发送请求,获取resposne
response = requests.get(url)
print(type(response.cookies))
​
#使用方法从cookiejar中提取数据  等同于  dict(response.cookies)
cookies = requests.utils.dict_from_cookiejar(response.cookies)
print(cookies)

输出为:

<class 'requests.cookies.RequestsCookieJar'>
{'BDORZ': '27315'}
注意:

在前面的requests的session类中,我们不需要处理cookie的任何细节,如果有需要,我们可以使用上述方法来解决

8、requests处理证书错误

经常我们在网上冲浪时,经常能够看到下面的提示:

出现这个问题的原因是:ssl的证书不安全导致

8.1 代码中发起请求的效果

那么如果在代码中请求会怎么样呢?

import requests
​
url = "https://www.12306.cn/mormhweb/"
response = requests.get(url)

返回证书错误,如下:

ssl.CertificateError ...

8.2 解决方案

为了在代码中能够正常的请求,我们修改添加一个参数

import requests
​
url = "https://www.12306.cn/mormhweb/"
response = requests.get(url,verify=False)

9、超时参数的使用

在平时网上冲浪的过程中,我们经常会遇到网络波动,这个时候,一个请求等了很久可能任然没有结果

在爬虫中,一个请求很久没有结果,就会让整个项目的效率变得非常低,这个时候我们就需要对请求进行强制要求,让他必须在特定的时间内返回结果,否则就报错

9.1 超时参数使用方法如下:

response = requests.get(url,timeout=3)

通过添加timeout参数,能够保证在3秒钟内返回响应,否则会报错

注意:

这个方法还能够拿来检测代理ip的质量,如果一个代理ip在很长时间没有响应,那么添加超时之后也会报错,对应的这个ip就可以从代理ip池中删除

10、retrying模块的使用

使用超时参数能够加快我们整体的请求速度,但是在正常的网页浏览过成功,如果发生速度很慢的情况,我们会做的选择是刷新页面,那么在代码中,我们是否也可以刷新请求呢?

对应的,retrying模块就可以帮助我们解决

10.1 retrying模块的使用

retrying模块的地址:https://pypi.org/project/retrying/

pip install retrying

retrying 模块的使用

  1. 使用retrying模块提供的retry模块

  2. 通过装饰器的方式使用,让被装饰的函数反复执行

  3. retry中可以传入参数stop_max_attempt_number,让函数报错后继续重新执行,达到最大执行次数的上限,如果每次都报错,整个函数报错,如果中间有一个成功,程序继续往后执行

10.2 retrying和requests的简单封装

实现一个发送请求的函数,每次爬虫中直接调用该函数即可实现发送请求,在其中

  • 使用timeout实现超时报错

  • 使用retrying模块实现重试

代码参考:

# parse.py
import requests
from retrying import retry
​
headers = {}
​
#最大重试3次,3次全部报错,才会报错
@retry(stop_max_attempt_number=3) 
def _parse_url(url)
    #超时的时候回报错并重试
    response = requests.get(url, headers=headers, timeout=3) 
    #状态码不是200,也会报错并重试
    assert response.status_code == 200
    return response
​
​
def parse_url(url)
    try: #进行异常捕获
        response = _parse_url(url)
    except Exception as e:
        print(e)
        #报错返回None
        response = None
    return response

11、扩展

**kwargs:控制访问的参数,均为可选项

  • params: 字典或字节序列,作为参数增加到url中

  • data:字典,字节序列或文件对象,作为Request的内容

  • headers: 字典, HTTP定制头

  • timeout: 设定超时时间,秒为单位

  • proxies [ˈprɑksiz] : 字典类型,设定访问代理服务器,可以增加登录认证

  • verify[ˈverəti] : True/False默认Ture,认证ssl证书开关

 

posted @ 2022-05-08 12:20  屠魔的少年  阅读(4)  评论(0)    收藏  举报