安装
pip install requests
如果您更喜欢使用 Pipenv 来管理 Python 包,则可以运行以下操作:
pipenv install requests
一旦安装了请求,就可以在应用程序中使用它。导入请求如下所示:
import requests
对于需要渲染有页面,推荐使用
requests-html
、Selenium
库。
GET请求
# 导入 requests 包
import requests
# 发送请求
x = requests.get('https://www.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://www.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://www.xushanxiang.com/media/avatar.jpg'
res = requests.get(URL)
photo = open('avatar.jpg','wb')
# 这里的文件没加路径,会被保存在程序运行的当前目录下。
photo.write(res.content)
# 将 Reponse 对象的内容以 [二进制数据] 的形式写入文件
photo.close()
下载音乐、视频和下载图片的思路代码几乎是一样的,只是 URL 的不同。
参考
- https://requests.readthedocs.io/zh_CN/latest/user/quickstart.html
- https://realpython.com/python-requests/