Python中的HTTP访问利器(python访问api)
Python里有不少能实现HTTP访问的利器,像requests库和urllib模块,用它们发起请求、处理响应超简单。
一、HTTP基础
HTTP(超文本传输协议)是Web通信的基础,它定义了客户端(如浏览器、Python程序)和服务器之间请求与响应的规则。一个完整的HTTP交互流程如下:
- 客户端发起请求:携带请求方法(如GET、POST)、URL、请求头、请求体等信息。
- 服务器处理请求:根据请求内容返回响应,包含状态码(如200表示成功)、响应头、响应体(如网页 HTML、JSON 数据)。
常见请求方法:
- GET:从服务器获取资源,常用于查询数据,请求参数附加在 URL 后。
- POST:向服务器提交数据,如表单提交、上传文件,参数在请求体中。
二、Python实现HTTP的访问
1. requests库:简洁高效的首选
requests库以简洁易用著称,只需几行代码就能完成HTTP请求。
安装:在命令行运行pip install requests。
基本使用(GET请求):
import requests
# 发送头条号网页的GET请求
params = {'key1': 'value1', 'key2': 'value2'}
response = requests.get('https://mp.toutiao.com', params=params,timeout=5)
# 检查响应状态码
if response.status_code == 200:
print("请求成功!")
print("响应内容(前50个字符):", response.text[:50])
else:
print(f"请求失败,状态码:{response.status_code}")
#输出为
请求成功!
响应内容(前50个字符): <!doctypehtml><html><head>
<script nonce='6bf7de99
基本使用(POST请求):
#post请求添加表单
data = {'username': 'user', 'password': '123456'}
response = requests.post('http://httpbin.org/post', data=data)
# 检查响应状态码
if response.status_code == 200:
print("请求成功!")
print("url:", response.url)
print("消息头:", response.headers)
print("消息体:", response.request.body)
print("响应内容(前50个字符):", response.text[:50])
else:
print(f"请求失败,状态码:{response.status_code}")
#输出为:
请求成功!
url: http://httpbin.org/post
消息头: {'Date': 'Sun, 27 Apr 2025 02:08:48 GMT', 'Content-Type': 'application/json', 'Content-Length': '510', 'Connection': 'keep-alive', 'Server': 'gunicorn/19.9.0', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': 'true'}
消息体: username=user&password=123456
响应内容(前50个字符): {
"args": {},
"data": "",
"files": {},
#post请求添加json数据
json_data = {'name': 'Alice', 'age': 25}
response = requests.post('http://httpbin.org/post', json=json_data)
# 检查响应状态码
if response.status_code == 200:
print("请求成功!")
print("url:", response.url)
print("消息头:", response.headers)
print("消息体:", response.request.body)
print("响应内容(前50个字符):", response.text[:50])
else:
print(f"请求失败,状态码:{response.status_code}")
#输出为:
请求成功!
url: http://httpbin.org/post
消息头: {'Date': 'Sun, 27 Apr 2025 02:08:48 GMT', 'Content-Type': 'application/json', 'Content-Length': '511', 'Connection': 'keep-alive', 'Server': 'gunicorn/19.9.0', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': 'true'}
消息体: b'{"name": "Alice", "age": 25}'
响应内容(前50个字符): {
"args": {},
"data": "{\"name\": \"Alice\",
关键函数与参数:
- requests.get(url, params=None, **kwargs):发送 GET 请求,params用于传递URL请求头的参数,timeout用于设置超时时间。
- requests.post(url, data=None, json=None, **kwargs):发送POST请求,data传递表单数据,json传递JSON数据。
- response.status_code:获取响应状态码。
- response.text:获取响应文本内容(字符串形式)。
- response.content:获取响应二进制内容(返回字节流,比如图片等非文本格式内容)。
- response.json():将响应内容解析为JSON对象(需响应为JSON格式)。
2. urllib模块:Python内置的 “老牌选手”
urllib是Python标准库的一部分,功能全面,适合更底层的HTTP操作。
基本使用(GET请求):
import urllib.request
#直接访问get请求
url = 'https://mp.toutiao.com'
try:
with urllib.request.urlopen(url) as response:
data = response.read().decode('utf-8')
print("请求成功!")
print("响应内容(前50个字符):", data[:50])
except urllib.error.URLError as e:
print(f"请求失败:{e}")
#添加请求头
req = urllib.request.Request(
url='https://mp.toutiao.com',
headers={'User-Agent': 'Mozilla/5.0'},
method='GET'
)
try:
with urllib.request.urlopen(req) as response:
data = response.read().decode('utf-8')
print("请求成功!")
print("响应内容(前50个字符):", data[:50])
except urllib.error.URLError as e:
print(f"请求失败:{e}")
基本使用(POST请求):
import urllib.request
from urllib.parse import urlencode
# 表单提交
data = urlencode({'user': 'admin', 'pass': 'secret'}).encode()
try:
with urllib.request.urlopen('http://httpbin.org/post', data=data) as response:
data = response.read().decode('utf-8')
print("请求成功!")
print("响应内容(前50个字符):", data[:50])
except urllib.error.URLError as e:
print(f"请求失败:{e}")
#输出为:
表单内容:b'user=admin&pass=secret'
请求成功!
响应内容(前50个字符): {
"args": {},
"data": "",
"files": {},
# JSON提交
import json
data = json.dumps({'id': 100}).encode('utf-8')
req = urllib.request.Request(
url='http://httpbin.org/post',
data=data,
headers={'Content-Type': 'application/json'}
)
try:
with urllib.request.urlopen(req) as response:
data = response.read().decode('utf-8')
print("请求成功!")
print("响应内容(前50个字符):", data[:50])
except urllib.error.URLError as e:
print(f"请求失败:{e}")
#输出为:
请求成功!
响应内容(前50个字符): {
"args": {},
"data": "{\"id\": 100}",
"fi
核心模块与函数:
- urllib.request.urlopen(url, data=None, **kwargs):打开 URL,data用于POST请求(需编码为字节流)。
- urllib.parse.urlencode将字典数据转换为key=value&key2=value2格式的字符串,并用encode('utf-8')将字符串转换为字节流,因为urlopen方法要求请求体是字节流。
- urllib.request.Request创建请求对象,将URL和请求体传入。
- urllib.error.URLError:捕获 URL 相关错误,如网络问题、服务器不可达。
- urllib.error.HTTPError:捕获 HTTP 响应错误(状态码非 200)。
3. aiohttp库:异步HTTP请求的 “快枪手”
aiohttp是用于异步I/O的HTTP客户端/服务器库,在处理大量并发请求时性能出色,特别适合异步编程场景,如爬虫、API 服务等。
安装:在命令行运行pip install aiohttp。
基本使用(异步GET请求):
import asyncio
import aiohttp
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
urls = [
"https://www.example1.com",
"https://www.example2.com",
"https://www.example3.com"
]
async with aiohttp.ClientSession() as session:
tasks = [fetch(session, url) for url in urls]
results = await asyncio.gather(*tasks)
for result in results:
print("响应内容(前50个字符):", result[:50])
asyncio.run(main())
核心函数与特点:
- aiohttp.ClientSession():创建客户端会话,用于管理 HTTP 连接。
- session.get(url, **kwargs) / session.post(url, **kwargs):发送 GET/POST 请求,支持异步操作。
- response.text():以文本形式获取响应内容,需配合await使用。
4. httpx库:集大成者
httpx结合了requests的简洁和aiohttp的异步功能,同时支持同步和异步请求,并且对HTTP/2协议有良好的支持。
安装:在命令行运行pip install httpx。
基本使用(GET请求):
import httpx
response = httpx.get('http://httpbin.org/')
if response.status_code == 200:
print("请求成功!")
print("响应内容(前50个字符):", response.text[:50])
else:
print(f"请求失败,状态码:{response.status_code}")
异步使用示例:
import asyncio
import httpx
async def async_fetch():
async with httpx.AsyncClient() as client:
response = await client.get('http://httpbin.org/')
if response.status_code == 200:
print("异步请求成功!")
print("响应内容(前50个字符):", response.text[:50])
else:
print(f"异步请求失败,状态码:{response.status_code}")
asyncio.run(async_fetch())
三、闭坑指南
请求超时问题
- 在requests中设置timeout参数,如response = requests.get(url, timeout=5)
- 在urllib中通过socket.setdefaulttimeout()设置全局超时。
- 在aiohttp中,可在请求时设置timeout=aiohttp.ClientTimeout(total=10) 。
- 在httpx中,同步请求使用httpx.get(url, timeout=5),异步请求使用await client.get(url, timeout=5)。
请求头缺失或错误
部分网站需要特定请求头(如User-Agent),缺失会导致请求被拒绝。在requests中通过headers参数添加请求头,如:
headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" } response = requests.get(url, headers=headers) |
- 在urllib中通过Request对象设置请求头:
req = urllib.request.Request(url, headers=headers)
- 在aiohttp中,在创建ClientSession时传入headers参数 ,如async with aiohttp.ClientSession(headers=headers) as session:。
- 在httpx中,同步和异步请求均可通过headers参数设置,如response = httpx.get(url, headers=headers) 、response = await client.get(url, headers=headers)。
响应内容解析错误
先通过response.headers.get('Content-Type')判断响应类型,再选择合适的解析方式。
SSL 证书验证问题
访问 HTTPS 网站时,证书验证失败导致请求中断。在requests中设置verify=False忽略证书验证(不建议在生产环境使用),或指定证书路径。在urllib中使用ssl模块处理证书。在aiohttp中,可通过connector=aiohttp.TCPConnector(ssl=False)忽略 SSL 验证(不推荐)。在httpx中,同步请求使用httpx.get(url, verify=False),异步请求使用await client.get(url, verify=False)(需谨慎使用)。
四、总结回顾
掌握Python的HTTP访问技能,无论是获取网页内容、调用API数据,还是与服务器交互,requests、urllib、aiohttp、httpx等库都能助你轻松完成。
附录、HTTP 访问常用函数汇总
库 / 模块 | 函数 / 方法 | 功能 |
requests | requests.get(url, params=None, **kwargs) | 发送 GET 请求 |
requests.post(url, data=None, json=None, **kwargs) | 发送 POST 请求 | |
response.status_code | 获取响应状态码 | |
response.text | 获取响应内容(字符串形式) | |
response.content | 获取响应内容(二进制形式) | |
response.json() | 将响应内容解析为 JSON 对象 | |
urllib.request | urllib.request.urlopen(url, data=None, **kwargs) | 打开 URL,发送请求 |
urllib.request.Request(url, data=None, headers=None, **kwargs) | 创建请求对象 | |
urllib.error.URLError | 捕获 URL 相关错误 | |
urllib.error.HTTPError | 捕获 HTTP 响应错误 | |
aiohttp | aiohttp.ClientSession() | 创建客户端会话 |
session.get(url, **kwargs) | 发送异步 GET 请求 | |
session.post(url, **kwargs) | 发送异步 POST 请求 | |
response.text() | 以文本形式获取响应内容 | |
httpx | httpx.get(url, **kwargs) | 发送同步 GET 请求 |