HTTP 状态码完全指南

深入理解 HTTP 状态码的含义与应用

简介: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 工具辅助调试