4、Requests库实战:发送GET请求、发送POST请求、处理请求参数、设置请求头、处理响应内容、超时与重试机制

好,咱们直接进入正题。Requests 这个库,说白了就是 Python 世界里最顺手的 HTTP 工具。我做了这么多年爬虫,90% 的请求都是用 Requests 搞定的。你想想看,如果连 Requests 都玩不转,那后面的 RPA 自动化、数据抓取基本就是空中楼阁。

这一节,我会把 Requests 最核心的六个操作掰开揉碎讲清楚。每个点我都会结合自己踩过的坑来聊,保证你听完就能上手。

4.1 发送GET请求:最基础的操作

GET 请求,就是向服务器要数据。比如你打开一个网页,浏览器就在发 GET 请求。

import requests

# 最简单的GET请求
response = requests.get('https://api.github.com')
print(response.status_code)  # 200 表示成功
print(response.text)  # 返回的文本内容

嗯,这里要注意。很多新手以为 GET 请求就是直接访问 URL 就完事了。其实不然。我在项目中遇到过,有些网站对 GET 请求的 User-Agent 有严格校验,你不设置请求头,直接返回 403。

我的习惯:每次发 GET 请求前,我都会先看一眼目标网站的 robots.txt,确认一下哪些路径可以抓。这不是怂,是职业素养。

4.2 发送POST请求:带数据的请求

POST 请求,说白了就是给服务器提交数据。比如登录、提交表单、上传文件,都是 POST。

# 发送POST请求,带表单数据
data = {'username': 'admin', 'password': '123456'}
response = requests.post('https://httpbin.org/post', data=data)
print(response.json())

为什么会这样?因为 POST 请求的数据是放在请求体里的,不像 GET 那样直接拼在 URL 上。我刚开始做爬虫时,就犯过这个错——把 POST 参数当 GET 参数拼在 URL 里,结果服务器死活不认。

避坑指南:我曾经在抓一个电商平台的登录接口时,发现 POST 数据明明是 JSON 格式,但服务器只认表单格式。后来才发现,Content-Type 没设置对。记住:data 参数默认是表单格式,json 参数才是 JSON 格式。

4.3 处理请求参数:灵活应对各种场景

请求参数,就是 URL 问号后面的那串东西。比如 ?page=1&size=20。手动拼接太容易出错了,我建议用 params 参数。

# 使用params参数
params = {'page': 1, 'size': 20, 'keyword': 'python'}
response = requests.get('https://httpbin.org/get', params=params)
print(response.url)  # 自动拼接成完整URL

你想想看,如果参数里有中文、特殊字符,手动拼接很容易出编码问题。Requests 的 params 会自动帮你做 URL 编码,省心多了。

参数类型 适用场景 示例
params GET请求的查询参数 params={'key': 'value'}
data POST请求的表单数据 data={'key': 'value'}
json POST请求的JSON数据 json={'key': 'value'}

4.4 设置请求头:伪装成正常浏览器

请求头,就是你和服务器打招呼时递上的名片。服务器一看你的名片,就知道你是浏览器还是爬虫。我见过太多新手,连 User-Agent 都不设置,直接裸奔去抓数据,结果被反爬虫系统秒封。

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
    'Accept': 'text/html,application/xhtml+xml',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Referer': 'https://www.google.com/'
}
response = requests.get('https://httpbin.org/headers', headers=headers)
核心要点:请求头里最重要的三个字段是 User-Agent、Referer 和 Cookie。User-Agent 告诉服务器你是什么浏览器,Referer 告诉服务器你从哪来,Cookie 告诉服务器你是谁。

我个人习惯,会把常用的请求头封装成一个字典,每次请求时直接传入。这样既统一又方便维护。我在项目中遇到过,有些网站会校验 Accept-Encoding,如果你不设置,它可能返回压缩后的数据,导致乱码。

4.5 处理响应内容:拿到数据只是第一步

响应内容,就是服务器给你的回复。可能是 HTML、JSON、图片、文件等等。怎么处理,取决于你的需求。

response = requests.get('https://api.github.com')

# 文本内容
print(response.text)  # 返回字符串

# JSON内容
print(response.json())  # 自动解析为字典

# 二进制内容
print(response.content)  # 返回字节流,适合下载图片

# 响应头
print(response.headers)  # 返回字典

# 状态码
print(response.status_code)  # 200, 404, 500等

嗯,这里有个坑。很多新手拿到 response.text 就直接用,但有时候编码不对,会出现乱码。我建议先检查 response.encoding,如果不对就手动设置。

# 手动设置编码
response.encoding = 'utf-8'
print(response.text)

4.6 超时与重试机制:让爬虫更健壮

网络请求,说白了就是不可靠的。服务器可能挂了,网络可能断了,请求可能超时。如果不设置超时,你的爬虫可能会卡死在那里,一直等下去。

# 设置超时时间(秒)
try:
    response = requests.get('https://httpbin.org/delay/5', timeout=3)
except requests.exceptions.Timeout:
    print('请求超时了,重试一下吧')

为什么会这样?因为有些接口响应很慢,或者网络不稳定。我建议把超时时间设置在 5-10 秒之间,太短容易误判,太长又浪费等待时间。

至于重试机制,我一般用两种方式:

  1. 手动重试:用循环加 try-except,失败后等几秒再试。
  2. 自动重试:requests.adapters.HTTPAdapter 配合 urllib3 的重试策略。
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

# 配置重试策略
retry_strategy = Retry(
    total=3,  # 总重试次数
    backoff_factor=1,  # 重试间隔:1, 2, 4, 8...秒
    status_forcelist=[500, 502, 503, 504]  # 哪些状态码需要重试
)

# 创建适配器
adapter = HTTPAdapter(max_retries=retry_strategy)

# 挂载到session
session = requests.Session()
session.mount('http://', adapter)
session.mount('https://', adapter)

# 使用session发送请求
response = session.get('https://httpbin.org/status/500')
我的经验:重试不是万能的。如果连续重试 3 次都失败,说明问题不在网络,可能是接口变了、IP 被封了、或者服务器真的挂了。这时候应该停下来检查,而不是无限重试。

你想想看,一个爬虫跑了一晚上,结果因为一个请求卡死了,后面的数据全没抓到,多亏啊。所以超时和重试,是每个爬虫工程师必须掌握的保命技能。

好了,Requests 库的六个核心操作就讲完了。从 GET 到 POST,从参数到请求头,从响应处理到超时重试,每一步都有讲究。我建议你把这些代码都敲一遍,遇到问题再回来翻翻。下一节,咱们聊聊 Session 和 Cookie 的管理,那才是真正进阶的开始。