简介:HTTP 状态码是服务器返回的三位数字代码,用于表示 HTTP 请求的处理结果。在爬虫开发和 Web 开发中,理解状态码对于调试和错误处理至关重要。本文将详细介绍各类 HTTP 状态码的含义、常见场景及处理方法。
一、HTTP 状态码分类
HTTP 状态码分为五大类,根据首位数字区分:
- 1xx:信息性响应,表示请求已接收,继续处理
- 2xx:成功响应,表示请求已成功被接收、理解、接受
- 3xx:重定向,表示需要进一步操作以完成请求
- 4xx:客户端错误,表示请求包含错误或无法完成
- 5xx:服务器错误,表示服务器无法完成有效请求
二、1xx 信息性响应
100 Continue
表示服务器已收到请求的初始部分,客户端应继续发送请求的剩余部分。
import requests
# 发送带有 Expect: 100-continue 的请求
headers = {'Expect': '100-continue'}
response = requests.post('https://api.example.com/upload',
headers=headers,
data='large data')
101 Switching Protocols
表示服务器已根据客户端的请求切换协议,常用于 WebSocket 连接。
三、2xx 成功响应
200 OK
请求成功,是最常见的成功状态码。
import requests
response = requests.get('https://api.example.com/data')
if response.status_code == 200:
print("请求成功")
print(response.json())
201 Created
请求成功并创建了新资源,常用于 POST 请求。
import requests
data = {'name': 'EasySpider', 'type': 'tool'}
response = requests.post('https://api.example.com/create', json=data)
if response.status_code == 201:
print("资源创建成功")
print(f"新资源位置: {response.headers.get('Location')}")
204 No Content
请求成功,但响应体为空,常用于 DELETE 请求。
四、3xx 重定向
301 Moved Permanently
资源已永久移动到新位置,搜索引擎会更新索引。
import requests
# Requests 默认会自动跟随重定向
response = requests.get('https://example.com/old-url')
print(f"最终URL: {response.url}")
print(f"重定向历史: {response.history}")
302 Found
资源临时移动到新位置,搜索引擎不会更新索引。
304 Not Modified
资源未修改,可使用缓存版本,常用于条件请求。
import requests
headers = {'If-None-Match': '"abc123"'}
response = requests.get('https://api.example.com/data', headers=headers)
if response.status_code == 304:
print("资源未修改,使用缓存")
五、4xx 客户端错误
400 Bad Request
请求格式错误或包含无效参数。
import requests
data = {'invalid': 'data'}
response = requests.post('https://api.example.com/create', json=data)
if response.status_code == 400:
print("请求错误")
print(response.json()) # 查看错误详情
401 Unauthorized
未授权,需要身份验证。
import requests
# 添加认证信息
headers = {'Authorization': 'Bearer your_token'}
response = requests.get('https://api.example.com/protected', headers=headers)
403 Forbidden
服务器理解请求但拒绝执行,通常是因为权限不足。
404 Not Found
请求的资源不存在。
import requests
response = requests.get('https://api.example.com/nonexistent')
if response.status_code == 404:
print("资源不存在")
429 Too Many Requests
请求过于频繁,触发了速率限制。
import requests
import time
response = requests.get('https://api.example.com/data')
if response.status_code == 429:
# 获取重试时间
retry_after = int(response.headers.get('Retry-After', 60))
print(f"请求过于频繁,{retry_after}秒后重试")
time.sleep(retry_after)
# 重试请求
response = requests.get('https://api.example.com/data')
六、5xx 服务器错误
500 Internal Server Error
服务器内部错误,通常是服务器端代码问题。
502 Bad Gateway
网关或代理服务器从上游服务器收到无效响应。
503 Service Unavailable
服务器暂时无法处理请求,通常是因为维护或过载。
import requests
import time
def fetch_with_retry(url, max_retries=3):
for i in range(max_retries):
response = requests.get(url)
if response.status_code == 503:
print(f"服务不可用,重试 {i+1}/{max_retries}")
time.sleep(2 ** i) # 指数退避
else:
return response
return None
504 Gateway Timeout
网关或代理服务器未及时从上游服务器收到响应。
七、爬虫中的状态码处理
7.1 基本状态码检查
import requests
def fetch_url(url):
try:
response = requests.get(url, timeout=10)
# 检查状态码
if response.status_code == 200:
return response.text
elif response.status_code == 404:
print(f"资源不存在: {url}")
elif response.status_code == 403:
print(f"访问被拒绝: {url}")
elif response.status_code == 429:
print(f"请求过于频繁: {url}")
elif response.status_code >= 500:
print(f"服务器错误: {url}")
else:
print(f"未知状态码: {response.status_code}")
except requests.exceptions.RequestException as e:
print(f"请求异常: {e}")
return None
7.2 自动重试机制
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
import requests
# 配置重试策略
retry_strategy = Retry(
total=3, # 最大重试次数
backoff_factor=1, # 重试间隔因子
status_forcelist=[429, 500, 502, 503, 504], # 需要重试的状态码
allowed_methods=["HEAD", "GET", "OPTIONS"] # 允许重试的请求方法
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session = requests.Session()
session.mount("http://", adapter)
session.mount("https://", adapter)
# 使用 session 发送请求
response = session.get('https://api.example.com/data')
7.3 处理重定向
import requests
# 禁止自动重定向
response = requests.get('https://example.com', allow_redirects=False)
if 300 <= response.status_code < 400:
print(f"重定向到: {response.headers.get('Location')}")
# 限制重定向次数
response = requests.get('https://example.com', max_redirects=5)
print(f"重定向次数: {len(response.history)}")
八、常见问题与解决方案
常见问题:
- 403 错误:检查 User-Agent、Cookie、Referer 等请求头
- 429 错误:添加请求延迟,使用代理 IP
- 503 错误:实现重试机制,添加指数退避
- 超时错误:设置合理的 timeout 参数
九、使用 EasySpider 辅助调试
EasySpider 提供的工具可以帮助你调试 HTTP 请求:
- Curl 转 Python:将浏览器中的请求转换为代码
- URL 参数提取:分析请求参数
- IP 查询:检查 IP 信息和地理位置
- 文本对比:比较不同请求的响应差异
总结
掌握 HTTP 状态码对于开发和调试非常重要。通过本文的学习,你应该能够:
- 理解各类 HTTP 状态码的含义
- 正确处理不同的状态码
- 实现重试和错误处理机制
- 使用 EasySpider 工具辅助调试