6

Python请求库requests使用指南

 9 months ago
source link: https://xushanxiang.com/python-requests.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Python-Requests-Library-Tutorial.jpg
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': '[email protected]', '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/

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK