在自动化脚本里调用 API 接口,最常用的 Python 库是 requests。相比标准库 urllib,它的 API 设计更贴近人类阅读习惯,几行代码就能完成一个带超时和异常处理的请求。本文不局限于发一个简单请求,而是围绕真实脚本中会遇到的问题展开:如何构造查询参数、如何处理认证、如何让脚本在网络波动时自动重试,以及如何把接口数据稳定写入文件。

安装 requests 并发送第一个 GET 请求
使用 pip 安装 requests 库:
pip install requests
安装完成后,先向 GitHub 公开接口发送一个 GET 请求,获取 requests 仓库的基本信息。这里不涉及认证,适合作为第一个测试。
import requests
response = requests.get('https://api.github.com/repos/psf/requests')
print(response.status_code)
print(response.json()['full_name'])response.status_code 返回 HTTP 状态码,200 表示成功。response.json() 会把响应体解析为字典或列表。如果接口返回的不是 JSON,调用它会抛出 JSONDecodeError,所以在生产中通常先判断状态码再解析。响应对象还提供 response.text、response.headers 等属性,方便排查问题。
实际的 GET 请求经常需要携带查询参数,比如搜索仓库、分页或过滤。requests 允许用 params 传入字典,库会自动完成 URL 编码。这样做比手动拼接字符串更安全,能避免中文、空格等特殊字符导致请求失败。
import requests
url = 'https://api.github.com/search/repositories'
params = {'q': 'language:python', 'sort': 'stars', 'order': 'desc'}
headers = {'Accept': 'application/vnd.github+json'}
resp = requests.get(url, params=params, headers=headers, timeout=10)
print(resp.url)
if resp.status_code == 200:
data = resp.json()
print('总数量:', data['total_count'])
for item in data['items'][:3]:
print(item['full_name'], item['stargazers_count'])上面代码中的 headers 用于告诉 GitHub 我们希望获得 JSON 格式的返回,timeout=10 表示最多等待 10 秒。只要网络正常,这个脚本就能输出搜索到的仓库名称和星数。这是自动化脚本中最基础的 GET 请求模式。
POST 请求与认证信息处理
很多接口不仅需要读取数据,还需要创建或修改资源,这时会用到 POST。requests 发送 POST 时,可以用 data 参数提交表单编码内容,也可以用 json 参数直接发送 JSON 数据。两者最大的区别是请求头中的 Content-Type 不同:data 默认使用 application/x-www-form-urlencoded,json 则使用 application/json。
下面这个例子向 httpbin.org 发送 JSON 数据,并带上了自定义 User-Agent 和 Bearer Token。实际项目中 Token 通常从环境变量读取,而不是硬编码在代码里。
import os
import requests
url = 'https://httpbin.org/post'
payload = {'name': '自动化脚本', 'type': 'demo'}
headers = {'User-Agent': 'python-script'}
token = os.getenv('API_TOKEN', '')
if token:
headers['Authorization'] = f'Bearer {token}'
resp = requests.post(url, json=payload, headers=headers, timeout=10)
print(resp.status_code)
print(resp.json()['json'])如果需要使用 HTTP Basic Auth,可以直接传 auth=('username', 'password')。requests 会自动生成 Authorization 头。对于大多数现代 API,更常见的是 Bearer Token 或 OAuth2,需要把 Token 放在 Authorization 头中。无论哪种方式,都不建议把密钥提交到版本库,使用环境变量或配置文件管理会更安全。
另一个容易忽略的细节是请求头中 Content-Type 的设置。手动指定错误类型可能导致服务端解析不了请求体。使用 json=payload 时 requests 会自动设置合适的头,不需要额外声明。如果确实需要覆盖,可在 headers 中显式指定,但要确保与实际发送的数据格式一致。
使用 Session 复用连接并引入超时重试
如果脚本需要连续请求同一个 API 服务,每次 requests.get() 都会创建新的 TCP 连接和 TLS 握手,这会增加延迟和资源消耗。改用 requests.Session 可以复用底层连接,自动保存 Cookie,还能统一设置默认头和默认超时。
下面的示例创建一个 Session,并配置自动重试策略。这里的 Retry 来自 urllib3,当遇到 500、502、503、504 等临时服务端错误时,会自动重试最多 3 次,每次间隔按 0.5 秒、1 秒、2 秒递增。
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
session = requests.Session()
retry = Retry(total=3, backoff_factor=0.5, status_forcelist=[500, 502, 503, 504])
adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)
try:
resp = session.get('https://api.github.com', timeout=5)
resp.raise_for_status()
print(resp.status_code)
except requests.exceptions.RequestException as e:
print(f'请求失败:{e}')
raise_for_status() 是一个很有用的方法,状态码在 400 到 599 之间时会主动抛出异常,省去手动判断的步骤。不过它只针对 HTTP 状态码,连接超时、DNS 解析失败等网络异常需要另外捕获。这里的 except requests.exceptions.RequestException 可以覆盖大多数 requests 抛出的异常。
除了依赖 urllib3 的自动重试,也可以自己实现简单的线性重试逻辑。比如在循环中尝试 3 次,失败后 time.sleep(2) 再继续。这种手动方式更透明,适合需要对不同异常采取不同退避策略的场景。
实战:定时调用天气接口并写入本地文件
把前面几节的内容组合起来,可以写一个完整的自动化脚本。这里选择 Open-Meteo 提供的免费天气接口,不需要申请 Key,适合本地测试。脚本会每隔 10 分钟请求一次北京地区的温度与湿度,然后把时间、温度、湿度追加写入 CSV 文件。
注意文件路径在 Windows 下使用反斜杠,例如 C:\data\weather.csv。在 Python 字符串里,反斜杠是转义字符,所以建议使用 raw string 或正斜杠。下面代码使用 r'C:\data' 来保留原始反斜杠,避免意外转义。
import csv
import os
import time
from datetime import datetime
import requests
def fetch_weather():
url = 'https://api.open-meteo.com/v1/forecast'
params = {
'latitude': 39.9042,
'longitude': 116.4074,
'hourly': 'temperature_2m,relative_humidity_2m',
'forecast_days': 1
}
headers = {'User-Agent': 'python-weather-script'}
response = requests.get(url, params=params, headers=headers, timeout=10)
response.raise_for_status()
data = response.json()
temp = data['hourly']['temperature_2m'][0]
humidity = data['hourly']['relative_humidity_2m'][0]
return datetime.now().isoformat(), temp, humidity
output_dir = r'C:\data'
os.makedirs(output_dir, exist_ok=True)
output_file = os.path.join(output_dir, 'weather.csv')
while True:
try:
timestamp, temp, humidity = fetch_weather()
with open(output_file, 'a', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow([timestamp, temp, humidity])
print(f'{timestamp} 写入成功:{temp}°C,{humidity}%')
except requests.exceptions.RequestException as e:
print(f'请求异常:{e}')
except Exception as e:
print(f'其他异常:{e}')
time.sleep(600)
这段代码中的 os.makedirs 会在目录不存在时自动创建,exist_ok=True 避免目录已存在时报错。open 使用追加模式 'a',每次运行不会清空之前的数据。newline='' 是为了防止 CSV 文件在 Windows 下出现多余空行。异常捕获分成两层,请求异常打印后继续循环,其他异常也不会让脚本直接退出。
如果希望脚本更健壮,可以把 sleep 时间改成可配置参数,或者使用 schedule 库来管理运行周期。还可以把请求失败的原因写入日志文件,方便后续排查。核心思路是让单个请求失败不影响整个自动化任务,同时保证每次请求都有超时上限,避免线程一直阻塞。
Python API调用自动化脚本HTTP请求修改时间:2026-09-18 09:56:46