Python请求库requests使用指南

作者: xusx 分类: Python 发布时间: 2023-11-27 12:45 浏览:51

安装

pip install requests

如果您更喜欢使用 Pipenv 来管理 Python 包,则可以运行以下操作:

pipenv install requests

一旦安装了请求,就可以在应用程序中使用它。导入请求如下所示:

import requests

对于需要渲染有页面,推荐使用 requests-htmlSelenium 库。

GET请求

# 导入 requests 包
import requests

# 发送请求
x = requests.get('https://xushanxiang.com/')

# 返回 http 的状态码:200
print(x.status_code)

# 响应状态的描述:OK
print(x.reason)

# 返回编码:utf-8
print(x.apparent_encoding)

# 把返回数据转成二进制,用于获取图片、音频类的数据
print(x.content)

# 把返回数据转为字符串,用于获取文本、网页原代码类的数据
print(x.text)

由于将字节解码为 str 需要一个编码方案,因此如果不指定编码方案,请求将尝试根据响应的标头猜测编码。您可以通过在访问 .text 之前设置 .concoding 来提供显式编码:

>>> x.encoding = 'utf-8' # 可选:设置可接收的编码为 utf-8
>>> x.text

requests 的方便之处还在于,对于特定类型的响应,例如JSON,可以直接获取。一般的,要获得字典,您可以获取从 .text 中检索到的 str,并使用 json.loads() 对其进行反序列化。然而,完成此任务的更简单方法是使用 .json() :

# 返回 json 数据
print(x.json())

Headers

响应标头可以为您提供有用的信息,例如响应负载的内容类型和缓存响应的时间限制。要查看这些标头,请访问 .headers :

print(x.headers)

{'Server': 'nginx', 'Date': 'Mon, 27 Nov 2023 02:35:27 GMT', 'Content-Type': 'text/html; charset=UTF-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding, Cookie', 'Cache-Control': 'max-age=3, must-revalidate', 'Content-Encoding': 'gzip'}

.headers 返回一个类似字典的对象,允许您按键访问头值。例如,要查看响应负载的内容类型,可以访问内容类型:

print(x.headers['Content-Type'])

text/html; charset=UTF-8

自定义请求头

# 设置请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit',
    'Content-Type': 'application/json;charset=UTF-8'
}

# params 接收一个字典或者字符串的查询参数,字典类型自动转换为url编码,不需要urlencode()
x = requests.get("https://xxx.com/", headers = headers)

url 传参

payload = {'key1': 'value1', 'key2': 'value2'}

x = requests.get("https://xxx.com/get", params=payload)
x.url # 看一下拼接好的 url
# https://xxx.com/get?key2=value2&key1=value1

字典里值为 None 的键都不会被添加到 URL 的查询字符串里。你还可以将一个列表作为值传入:

payload = {'key1': 'value1', 'key2': ['value2', 'value3']}
x = requests.get('https://xxx.com/get', params=payload)
print(x.url)

# https://xxx.com/get?key1=value1&key2=value2&key2=value3

POST请求

requests.post(url, data={key: value}, json={key: value}, args)

要发送POST请求,只需要把 get() 方法变成 post(),然后传入data参数作为 POST 请求的数据:

x = requests.post('https://xxx.com/login', data={'form_email': 'abc@example.com', 'form_password': '123456'})

requests默认使用 application/x-www-form-urlencoded 对 POST 数据编码。如果要传递 JSON 数据,可以直接传入 json 参数:

params = {'key': 'value'}
x = requests.post(url, json=params) # 内部自动序列化为JSON

其他HTTP方法

除了 GET 和 POST,其他流行的 HTTP 方法还包括 PUT、DELETE、HEAD、PATCH 和 OPTIONS 。requests 为以下每个 HTTP 方法提供了一个方法,该方法具有与 get() 类似的签名:

>>> requests.put('https://xxx.com/put', data={'key':'value'})
>>> requests.delete('https://xxx.com/delete')
>>> requests.head('https://xxx.com/get')
>>> requests.patch('https://xxx.com/patch', data={'key':'value'})
>>> requests.options('https://xxx.com/get')

模拟登录

模拟登录一般是 HTTP POST 请求,如果没有验证码的话非常简单(需要使用图像识别相关库),典型代码为:

import requests
import json

headers = {
  'user-agent': 'Mozilla/5.0...',
   # 无格式要求不指定
   'Content-Type': 'application/json;charset=UTF-8'
}
# 其他 {'Content-Type': 'application/x-www-form-urlencoded'}
s = requests.session()
login_data = dict(userName='xxx', password='xxxx')
s.post('https://xxx.com/login',data=json.dumps(login_data),headers=headers)
# 无格式要求直接传 login_data
# 获取网页内容
x = s.get('https://xxx.com')

上传文件

上传文件需要更复杂的编码格式,但是 requests 把它简化成files参数:

upload_files = {'file': open('report.xls', 'rb')}
x = requests.post(url, files=upload_files)

在读取文件时,注意务必使用'rb'即二进制模式读取,这样获取的bytes长度才是文件的长度。你还可以显式地设置文件名,文件类型和请求头:

url = 'https://xxx.com/post'
files = {
    'file': ('report.xls', open('report.xls', 'rb'),
    'application/vnd.ms-excel',
    {'Expires': '0'})
}
x = requests.post(url, files=files)
x.text
'''
{
  ...
  "files": {
    "file": "<censored...binary...data>"
  },
  ...
}
'''

如果你发送一个非常大的文件作为 multipart/form-data 请求,你可能希望将请求做成数据流。默认下 requests 不支持,但有个第三方包 requests-toolbelt 是支持的。你可以阅读 toolbelt 文档 来了解使用方法。

SSL证书验证

任何时候,您试图发送或接收的数据都是敏感的,安全性很重要。通过 HTTP 与安全站点通信的方式是使用 SSL 建立加密连接,这意味着验证目标服务器的 SSL 证书至关重要。
好消息是,默认情况下请求会为您执行此操作。但是,在某些情况下,您可能想要更改这种行为。
如果要禁用 SSL 证书验证,请将 False 传递给请求函数的验证参数:

>>> requests.get('https://xxx.com', verify=False)

InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)
<Response [200]>

请求甚至会在你提出不安全的请求时警告你,以帮助你保护数据的安全!

设置超时时间

>>> requests.get('https://xxx.com', timeout=1)
>>> requests.get('https://xxx.com', timeout=3.05)
>>> requests.get('https://xxx.com', timeout=(2, 5))

完整示例:

import requests
from requests.exceptions import Timeout

try:
    response = requests.get('https://xxx.com', timeout=1)
except Timeout:
    print('The request timed out')
else:
    print('The request did not time out')

最大重试次数

当请求失败时,您可能希望应用程序重试相同的请求。但是,默认情况下,请求不会为您执行此操作。若要应用此功能,您需要实现一个自定义传输适配器。

传输适配器允许您为与之交互的每个服务定义一组配置。例如,假设您希望所有请求 https://xxx.com 在最终引发 ConnectionError 之前重试三次。您将构建一个传输适配器,设置其 max_retrys 参数,并将其装载到现有会话:

import requests
from requests.adapters import HTTPAdapter
from requests.exceptions import ConnectionError

xxx_adapter = HTTPAdapter(max_retries=3)
session = requests.Session()
session.mount('https://xxx.com', xxx_adapter)

try:
    session.get('https://xxx.com')
except ConnectionError as ce:
    print(ce)

Cookie

requests 对 Cookie 做了特殊处理,使得我们不必解析 Cookie 就可以轻松获取指定的Cookie:

url = 'http://xxx.com/some/cookie/setting/url'
x = requests.get(url)
x.cookies['example_cookie_name']
# 'example_cookie_value'

要在请求中传入 Cookie,只需准备一个 dict 传入cookies参数:

cs = {'token': '12345', 'status': 'working'}
x = requests.get(url, cookies=cs)

Cookie 的返回对象为 RequestsCookieJar,它的行为和字典类似,但接口更为完整,适合跨域名跨路径使用。你还可以把 Cookie Jar 传到 Requests 中:

jar = requests.cookies.RequestsCookieJar()
jar.set('tasty_cookie', 'yum', domain='xxx.com', path='/cookies')
jar.set('gross_cookie', 'blech', domain='xxx.com', path='/elsewhere')
url = 'http://xxx.com/cookies'
r = requests.get(url, cookies=jar)
r.text
# '{"cookies": {"tasty_cookie": "yum"}}'

简单多线程

如果感觉访问太慢,可以用多线程解决。以下是一个简单的多线程用户示例:

def get_data(page_id):
    url = f'https://xxx.com/Page?Id='
    r = s.get(url)
    df = pd.DataFrame(r.json()['data']['items'])
    df.to_csv(f'card/xxx-{page_id}.csv')
    print(f'{page_id}页已获取')

def run(start, end):
    for i in range(start, end+1):
        get_data(i)

# 引入相关库
import threading
import time

# 分批同时执行
%%time
t1 = threading.Thread(target=run, args=(1, 100))
t2 = threading.Thread(target=run, args=(101, 200))
t3 = threading.Thread(target=run, args=(201, 300))

t1.start()
t2.start()
t3.start()

内容写入文本文件

import requests

URL = 'https://xushanxiang.com/'
res = requests.get(URL)
res.encoding = 'utf-8'
file = open('xushanxiang.txt', 'a+')
file.write(res.text)
file.close()

下载图片文件

import requests

URL = 'https://xushanxiang.com/media/avatar.jpg'
res = requests.get(URL)
photo = open('avatar.jpg','wb')
# 这里的文件没加路径,会被保存在程序运行的当前目录下。
photo.write(res.content)
# 将 Reponse 对象的内容以 [二进制数据] 的形式写入文件
photo.close()

下载音乐、视频和下载图片的思路代码几乎是一样的,只是 URL 的不同。

参考

  1. https://requests.readthedocs.io/zh_CN/latest/user/quickstart.html
  2. https://realpython.com/python-requests/

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!