HTTP 基础
理解 HTTP 协议是写好爬虫的基础。本章将介绍 HTTP 的核心概念,帮助你更好地理解网络请求和响应。
什么是 HTTP?
HTTP(HyperText Transfer Protocol,超文本传输协议)是客户端和服务器之间的通信协议。当你在浏览器中访问一个网页时,浏览器会向服务器发送 HTTP 请求,服务器则返回 HTTP 响应。
URL 详解
URL(Uniform Resource Locator,统一资源定位符)是网页的地址。一个完整的 URL 包含多个部分:
https://www.example.com:443/path/to/page?id=123#section
│ │ │ │ │ │
│ │ │ │ │ └─ 锚点(不发送给服务器)
│ │ │ │ └─────────── 查询参数
│ │ │ └────────────────────────── 路径
│ │ └────────────────────────────── 端口
│ └──────────────────────────────────────────── 域名
└──────────────────────────────────────────────────── 协议
URL 各部分说明:
| 部分 | 说明 | 示例 |
|---|---|---|
| 协议 | 通信协议 | http, https, ftp |
| 域名 | 服务器地址 | www.example.com |
| 端口 | 服务端口(可选) | :443, :8080 |
| 路径 | 资源位置 | /path/to/page |
| 查询参数 | 传递给服务器的参数 | ?id=123&page=1 |
| 锚点 | 页面内定位 | #section |
HTTP 请求
请求方法
HTTP 定义了多种请求方法,最常用的是 GET 和 POST:
| 方法 | 说明 | 用途 |
|---|---|---|
| GET | 获取资源 | 浏览网页、获取数据 |
| POST | 提交数据 | 登录、提交表单 |
| PUT | 更新资源 | 更新数据 |
| DELETE | 删除资源 | 删除数据 |
| HEAD | 获取响应头 | 检查资源是否存在 |
GET 请求
GET 请求将参数放在 URL 中,用于请求数据:
GET /search?q=python&page=1 HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0
Accept: text/html
特点:
- 参数暴露在 URL 中
- 适合查询操作
- 有长度限制(浏览器通常限制 2000 字符左右)
POST 请求
POST 请求将数据放在请求体中,用于提交数据:
POST /login HTTP/1.1
Host: www.example.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0
username=admin&password=123456
特点:
- 数据放在请求体中,更安全
- 无大小限制
- 适合提交表单、上传文件
请求头
请求头包含关于请求的元数据:
# 常见的请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive',
'Referer': 'https://www.example.com/', # 来源页面
'Cookie': 'session_id=abc123', # Cookie 信息
}
常用请求头说明:
| 请求头 | 说明 |
|---|---|
| User-Agent | 标识客户端类型(浏览器/爬虫) |
| Accept | 告诉服务器客户端能接受的响应类型 |
| Accept-Language | 接受的语言 |
| Accept-Encoding | 可接受的编码方式(如 gzip) |
| Referer | 请求的来源页面 |
| Cookie | 携带的 Cookie 信息 |
HTTP 响应
状态码
HTTP 响应包含一个状态码,表示请求的结果:
常见状态码:
| 状态码 | 含义 | 说明 |
|---|---|---|
| 200 | OK | 请求成功 |
| 201 | Created | 资源创建成功 |
| 301 | Moved Permanently | 永久重定向 |
| 302 | Found | 临时重定向 |
| 304 | Not Modified | 资源未修改,使用缓存 |
| 400 | Bad Request | 请求语法错误 |
| 401 | Unauthorized | 需要认证 |
| 403 | Forbidden | 拒绝访问 |
| 404 | Not Found | 资源不存在 |
| 429 | Too Many Requests | 请求过于频繁 |
| 500 | Internal Server Error | 服务器内部错误 |
| 502 | Bad Gateway | 网关错误 |
| 503 | Service Unavailable | 服务不可用 |
| 504 | Gateway Timeout | 网关超时 |
响应头
响应头包含关于响应的元数据:
# 常见的响应头
response.headers = {
'Content-Type': 'text/html; charset=utf-8', # 内容类型
'Content-Length': '12345', # 内容长度
'Server': 'nginx/1.18.0', # 服务器类型
'Date': 'Sat, 25 Mar 2024 00:00:00 GMT', # 响应时间
'Set-Cookie': 'session=abc123; HttpOnly', # 设置 Cookie
'Cache-Control': 'no-cache', # 缓存控制
'Expires': 'Sat, 25 Mar 2024 00:00:00 GMT', # 过期时间
}
响应体
响应体是服务器返回的实际内容,常见格式:
- HTML - 网页内容
- JSON - API 接口常用
- XML - 某些老旧 API 使用
- 图片/视频/文件 - 二进制数据
- 纯文本 - 简单文本内容
Cookie 和 Session
Cookie 机制
Cookie 是服务器保存在客户端的数据,用于维持会话状态:
在爬虫中使用 Cookie
import requests
# 方式1:手动设置 Cookie
cookies = {
'session_id': 'abc123',
'user_token': 'xyz789'
}
response = requests.get('https://example.com/profile', cookies=cookies)
# 方式2:使用 Session 自动管理 Cookie
session = requests.Session()
# 登录(服务器会设置 Cookie)
session.post('https://example.com/login', data={
'username': 'user',
'password': 'pass'
})
# 后续请求会自动携带 Cookie
response = session.get('https://example.com/profile')
print(response.text)
Session 和 Token
Session 认证
传统的会话认证方式:
# Session 认证流程
session = requests.Session()
# 1. 登录
login_data = {
'username': 'your_username',
'password': 'your_password'
}
session.post('https://example.com/login', data=login_data)
# 2. 访问需要登录的页面
response = session.get('https://example.com/member/info')
Token 认证
现代 API 常用的认证方式:
import requests
# 1. 获取 Token
auth_data = {
'username': 'your_username',
'password': 'your_password'
}
response = requests.post('https://example.com/api/login', json=auth_data)
token = response.json()['token']
# 2. 使用 Token 请求
headers = {
'Authorization': f'Bearer {token}'
}
response = requests.get('https://example.com/api/user', headers=headers)
HTTP 代理
使用代理可以隐藏真实 IP,避免被封禁:
import requests
# 使用代理
proxies = {
'http': 'http://127.0.0.1:7890',
'https': 'http://127.0.0.1:7890'
}
response = requests.get('https://example.com', proxies=proxies)
# 认证代理
proxies_with_auth = {
'http': 'http://user:[email protected]:7890',
}
HTTPS 和 SSL
HTTPS 是 HTTP 的安全版本,使用 SSL/TLS 加密:
import requests
# 忽略 SSL 证书验证(不推荐,仅用于测试)
response = requests.get('https://example.com', verify=False)
# 指定 SSL 证书
response = requests.get('https://example.com', cert='/path/to/cert.pem')
小结
本章我们学习了:
- URL 构成 - 协议、域名、端口、路径、查询参数
- HTTP 请求方法 - GET、POST 等
- 请求头和响应头 - HTTP 元数据
- 状态码 - 表示请求结果
- Cookie 和 Session - 会话管理
- 代理 - 隐藏真实 IP
理解这些 HTTP 基础知识对于编写高效的爬虫至关重要。
练习
- 使用浏览器开发者工具查看一个网页的请求和响应头
- 分析 URL 中的查询参数如何构造
- 理解 301、302、404、429 等常见状态码的含义