python requests 使用

环境信息

  • Python 3.11.2

安装

pip install requests

常见用法

get 请求

get 请求及响应中常用的属性

>>> r = requests.get('https://csms.tech')
>>> dir(r)
[..., 'content', 'cookies', 'elapsed', 'encoding', 'headers', 'history',
'is_permanent_redirect', 'is_redirect', 'iter_content', 'iter_lines',
'json', 'links', 'next', 'ok', 'raise_for_status', 'raw', 'reason',
'request', 'status_code', 'text', 'url']

带参数的 get 请求

要在 get 请求中携带请求参数,可以使用以下方法

>>> help(requests.get)
get(url, params=None, **kwargs)
Sends a GET request.

:param url: URL for the new :class:`Request` object.
:param params: (optional) Dictionary, list of tuples or bytes to send
in the query string for the :class:`Request`.
:param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response

>>> params = {'k1': 'v1', 'k2': 'v2'}
>>> r = requests.get('https://csms.tech', params=params)

# 设置请求头
>>> 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"}
>>> response = requests.get("https://csms.tech", params = params, headers = headers)

get 方法本质上是通过创建了一个 requests.Request 对象,因此 **kwargs 可用的值可以通过查看 requests.Request 的帮助信息。

>>> help(requests.Request)

post 请求

post 方法可以发送 POST 请求到指定 url,一般格式如下:

requests.post(url, data={key: value}, json={key: value}, args)
  • url - 请求 url。

  • data - 参数为要发送到指定 url 的字典、元组列表、字节或文件对象。

  • json - 参数为要发送到指定 url 的 JSON 对象。

  • args - 为其他参数,比如 cookies、headers、verify等。

提交 str 类型的 PSOT 数据

假设 HTTP POST 以下数据内容:

count_status2: DELIVRD
recv_time[]: 2024-07-01 00:00:00
recv_time[]: 2024-07-01 23:59:59
count: 7053

以上 POST 数据转换成 URI: count_status2=DELIVRD&recv_time%5B%5D=2024-07-01+00%3A00%3A00&recv_time%5B%5D=2024-07-01+23%3A59%3A59&count=7053

针对以上内容,如果使用 字典(Dict) 类型的数据结构提交 POST 数据,因为数据中包含重复键的内容,会导致请求失败。此时可以使用 str 格式提交 POST 数据,示例代码如下:

import requests

query_date = "2024-07-01"

total_records = 7053

export_url = 'http://sms.pinyuntech.cn/ustatistic/mt/_export'

payload = f"count_status2=DELIVRD&recv_time%5B%5D={query_date}+00%3A00%3A00&recv_time%5B%5D={query_date}+23%3A59%3A59&count={total_records}"

cookies_string = "; ".join([f"{cookie['name']}={cookie['value']}" for cookie in cookies])

headers = {
'accept': 'application/json, text/javascript, */*; q=0.01',
'accept-encoding': 'gzip, deflate',
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
'cookie': cookies_string,
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
'x-requested-with': 'XMLHttpRequest'
}

resp = requests.post(export_url, data=payload, headers=headers)

data 和 json 提交 POST 数据的不同

requests.post 方法中,datajson 参数的使用有所不同,它们主要区别在于 请求主体的内容类型和数据处理方式。以下是具体区别:

  1. data 参数

    • 内容类型 : data 参数通常用于发送 表单数据原始的字符串数据。默认情况下,内容类型(Content-Type)会被设置为 application/x-www-form-urlencoded,类似于 HTML 表单提交的数据格式。
    • 数据处理 : data 参数接受 字典元组列表字符串文件对象 。如果传递的是 字典元组列表requests 会将其编码为 URL 编码格式。如果传递的是 字符串文件对象requests 会直接使用它们的内容。

    示例如下:

    import requests

    # 使用 data 参数发送表单数据
    payload = {'key1': 'value1', 'key2': 'value2'}
    response = requests.post('http://example.com/api', data=payload)

    print("Response code:", response.status_code)
    print("Response text:", response.text)


    在这个示例中,requests 会将 payload 编码为 key1=value1&key2=value2 的 URL 编码格式。

  2. json 参数

    • 内容类型 : json 参数用于发送 JSON 格式的数据。使用 json 参数时,内容类型(Content-Type)会自动设置为 application/json
    • 数据处理 : json 参数接受一个 字典,它会被 requests 库自动转换为 JSON 字符串,然后发送出去。
    import requests

    # 使用 json 参数发送 JSON 数据
    payload = {'key1': 'value1', 'key2': 'value2'}
    response = requests.post('http://example.com/api', json=payload)

    print("Response code:", response.status_code)
    print("Response text:", response.text)

    在这个示例中,requests 会将 payload 转换为 JSON 字符串 {"key1": "value1", "key2": "value2"},并将内容类型设置为 application/json

选择使用 data 还是 json

  • 使用 data : 当你需要发送 表单数据简单的字符串数据 时,使用 data 参数。
  • 使用 json : 当你需要发送 JSON 数据时,使用 json 参数。

错误使用案例

使用 POST 方式提交以下数据到服务器

payload = {
'account': 'user1',
'app_key': 'cl_international_sms',
'page_no': 1,
'page_size': 10,
'start_time': f'{last_month_year}-{last_month:02d}',
'end_time': f'{last_month_year}-{last_month:02d}',
}

headers = {
'accept': 'application/json, text/plain, */*',
'accept-encoding': 'gzip, deflate, br, zstd',
'content-type': 'application/json',
'cookie': cookies_string,
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
'token': token
}

假如使用 data 方式提交:

resp = requests.post(url, data=payload, headers=headers)
print(f"response: {resp.status_code}, text: {resp.text}")

服务器可能会返回类似错误: response: 200, text: {"code":"000998","message":"web未知异常"}

错误原因 : 使用 data 提交 POST 数据时,requests 会将其编码为 URL 编码格式(application/x-www-form-urlencoded),尽管在请求头中明确设置了 Content-Type: application/json,但实际上传递的数据仍然是 URL 编码格式的。导致请求的内容类型(Content-Type)与服务器期望的数据格式不匹配

请求方式改为以下方式可正常返回期望的数据:

resp = requests.post(url, json=payload, headers=headers)
print(f"response: {resp.status_code}, text: {resp.text}")