Skip to content

章节 1:爬虫基础与网络协议

学习目标

  • 深入理解 HTTP/HTTPS 协议的工作原理与报文结构
  • 掌握 Requests 库的 Session 管理、请求伪装等高级用法
  • 熟练使用 Fiddler 进行抓包、断点调试与请求修改
  • 了解爬虫法律风险、robots.txt 规范与职业伦理

1.1 HTTP/HTTPS 协议深度拆解

1.1.1 HTTP 协议基础

定义:HTTP(HyperText Transfer Protocol,超文本传输协议)是客户端与服务器之间传输超媒体文档的应用层协议,是爬虫与目标服务器通信的基础。

请求报文结构

http
POST /api/login HTTP/1.1          ← 请求行:方法 + URL + 版本
Host: example.com                  ← 请求头(Headers)
User-Agent: Mozilla/5.0 ...
Content-Type: application/json
Cookie: session_id=abc123

{"username":"admin","password":"123456"}  ← 请求体(Body)

响应报文结构

http
HTTP/1.1 200 OK                    ← 状态行:版本 + 状态码 + 短语
Content-Type: text/html; charset=utf-8
Set-Cookie: token=xyz789
Content-Length: 1234

<!DOCTYPE html><html>...</html>    ← 响应体(Body)

HTTP 方法速查表

方法语义是否有体幂等爬虫中用途
GET获取资源请求页面 / 公开数据
POST提交/创建资源登录、提交表单、API 查询
PUT全量更新资源更新数据
DELETE删除资源删除操作
PATCH部分更新资源局部更新

状态码分类

状态码范围类别常见状态码
1xx信息性100 Continue, 101 Switching Protocols
2xx成功200 OK, 201 Created, 204 No Content
3xx重定向301 Moved Permanently, 302 Found, 304 Not Modified
4xx客户端错误400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found
5xx服务端错误500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable

1.1.2 HTTPS 与 TLS 握手

定义:HTTPS = HTTP + SSL/TLS,通过加密通信保证数据传输的机密性、完整性和服务器身份验证。

TLS 1.3 握手过程(简化)

Client                                   Server
  │                                         │
  ├── ClientHello (支持的密码套件) ──────→  │
  │                                         ├── ServerHello (选定套件)
  │                                         ├── Certificate (服务器证书)
  │                                         ├── ServerFinished ──→
  │  ←── ClientFinished ──────────────────  │
  │  ←──────── 加密数据传输 ──────────────→  │

关键概念

  • 证书(Certificate):由 CA 签发,包含公钥和域名信息,验证服务器身份
  • 对称加密:使用共享密钥加密实际数据(如 AES),速度快
  • 非对称加密:使用公钥/私钥对交换对称密钥(如 RSA、ECDHE),仅用于握手阶段

定义:HTTP 是无状态协议,Cookie/Session 机制为服务器提供"记忆"能力。

工作原理

第一次请求:POST /login
  └→ 服务器验证身份后,创建 Session,返回 Set-Cookie: session_id=abc123

第二次请求:GET /profile   Cookie: session_id=abc123
  └→ 服务器根据 Cookie 查找 Session,识别用户身份

爬虫中处理 Cookie 的三种方式

python
# 方式一:直接传入字典
cookies = {"session_id": "abc123"}
resp = requests.get("https://example.com/profile", cookies=cookies)

# 方式二:使用 Session 对象自动管理
s = requests.Session()
s.post("https://example.com/login", data={"user": "admin", "pass": "123"})
resp = s.get("https://example.com/profile")  # 自动携带 Cookie

# 方式三:从浏览器导出 Cookie 字符串
cookies_str = "session_id=abc123; token=xyz789"
cookies_dict = {kv.split("=")[0].strip(): kv.split("=")[1].strip()
                for kv in cookies_str.split(";")}
resp = requests.get("https://example.com/profile", cookies=cookies_dict)

1.2 Requests 请求库进阶

1.2.1 Session 对象

定义requests.Session() 在同一个会话实例中持久化 Cookie、连接池和默认配置,适合需要维护登录状态的爬虫场景。

python
import requests

# 创建 Session
session = requests.Session()

# 设置全局默认 Headers
session.headers.update({
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
    "Accept-Language": "zh-CN,zh;q=0.9",
})

# 登录(Cookie 自动保存到 Session)
login_data = {"username": "test_user", "password": "test_pass"}
session.post("https://httpbin.org/post", data=login_data)

# 后续请求自动携带 Cookie
resp = session.get("https://httpbin.org/cookies")
print(resp.json())  # 包含登录后的 Cookie

1.2.2 GET 请求参数详解

python
import requests

# 基础 GET
resp = requests.get("https://api.github.com/search/repositories")

# URL 参数——方式一:params 字典
params = {"q": "python爬虫", "sort": "stars", "order": "desc"}
resp = requests.get("https://api.github.com/search/repositories", params=params)
print(resp.url)  # https://api.github.com/search/repositories?q=python爬虫&sort=stars&order=desc

# URL 参数——方式二:直接拼接
resp = requests.get("https://httpbin.org/get?page=1&size=20")

# 请求头伪装
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
    "Referer": "https://www.google.com/",
    "Origin": "https://example.com",
    "X-Requested-With": "XMLHttpRequest",  # 标识 AJAX 请求
}
resp = requests.get("https://example.com/api/data", headers=headers)

# 超时设置(必设!)
resp = requests.get("https://example.com", timeout=(5, 10))
# timeout = (connect_timeout, read_timeout)

1.2.3 POST 请求与数据提交

python
import requests

# Form Data(application/x-www-form-urlencoded)
data = {"username": "admin", "password": "123456"}
resp = requests.post("https://httpbin.org/post", data=data)
print(resp.json()["form"])  # {'username': 'admin', 'password': '123456'}

# JSON Data(application/json)
json_data = {"name": "test", "age": 18}
resp = requests.post("https://httpbin.org/post", json=json_data)
print(resp.json()["json"])  # {'name': 'test', 'age': 18}

# Multipart(文件上传)
files = {
    "file": ("report.pdf", open("report.pdf", "rb"), "application/pdf"),
    "description": (None, "月度报告"),
}
resp = requests.post("https://httpbin.org/post", files=files)

1.2.4 Headers 伪装技巧

python
import requests

# 完整浏览器伪装
headers = {
    # 必须——标识客户端
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                  "AppleWebKit/537.36 (KHTML, like Gecko) "
                  "Chrome/120.0.0.0 Safari/537.36",

    # 来源——很多网站校验
    "Referer": "https://www.example.com/products",

    # 请求来源域名
    "Origin": "https://www.example.com",

    # AJAX 标识(很多 API 接口要求)
    "X-Requested-With": "XMLHttpRequest",

    # 接受的内容类型
    "Accept": "text/html,application/json,*/*",

    # 编码
    "Accept-Encoding": "gzip, deflate, br",

    # 语言偏好
    "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
}

1.2.5 异常处理与重试机制

python
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

# 带重试的 Session
session = requests.Session()

retry_strategy = Retry(
    total=3,                    # 总重试次数
    backoff_factor=1,           # 重试等待:1s, 2s, 4s
    status_forcelist=[500, 502, 503, 504],  # 这些状态码触发重试
    allowed_methods=["GET", "POST"],
)

adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("https://", adapter)
session.mount("http://", adapter)

try:
    resp = session.get("https://httpbin.org/status/500", timeout=5)
except requests.exceptions.ConnectionError:
    print("连接失败")
except requests.exceptions.Timeout:
    print("请求超时")
except requests.exceptions.RequestException as e:
    print(f"请求异常: {e}")

1.3 Fiddler 抓包工具

1.3.1 Fiddler 原理与安装

定义:Fiddler 是一款 HTTP/HTTPS 调试代理工具,通过设置本地代理(127.0.0.1:8888)拦截并记录所有经过的 HTTP/HTTPS 流量。

工作原理

浏览器/App ──→ Fiddler (代理 8888) ──→ 目标服务器

              流量记录、修改、重放

HTTPS 解密配置

  1. 菜单栏 → Tools → Options → HTTPS
  2. 勾选 "Capture HTTPS CONNECTs" 和 "Decrypt HTTPS traffic"
  3. 在弹出的安装证书窗口中确认(首次需要安装 Fiddler Root CA)

1.3.2 界面布局与核心功能

┌────────────────────────────────────────────────────────────────┐
│ 工具栏:注释 | 重放 | 清除 | 断点 | 解码 | 过滤              │
├───────────────────────┬────────────────────────────────────────┤
│                        │                                       │
│ 会话列表 (左侧)        │ 详情面板 (右侧)                       │
│                        │                                       │
│ #  Result  Proto  URL  │ 📄 Inspectors                        │
│ 200    200   HTTP  /a  │  ├─ Request: Headers / TextView / ... │
│ 201    301   HTTP  /b  │  └─ Response: Headers / TextView /... │
│ 202    404   HTTP  /c  │                                       │
│                        │ 🎯 AutoResponder / Composer / Fiddler │
├───────────────────────┴────────────────────────────────────────┤
│ 命令行 (底部):输入 help 查看命令                              │
└────────────────────────────────────────────────────────────────┘

常用命令行

命令说明
?keyword筛选 URL 包含关键字
>200筛选状态码大于 200
=200筛选状态码等于 200
@host.com筛选指定域名的请求
select image选中所有图片类型

1.3.3 断点调试与请求修改

全局断点(拦截所有请求)

  • 菜单栏 → Rules → Automatic Breakpoints → Before Requests
  • 或按快捷键 F11 切换

请求修改步骤

  1. Fiddler 拦截请求后,转到 Inspectors → Request
  2. 修改 Headers、Body 或 URL
  3. 点击 "Run to Completion"(或按 G 键)放行

示例:修改 User-Agent

拦截请求后,在 Headers 中找到 User-Agent 行
修改为:User-Agent: CustomBot/1.0
点击 "Run to Completion"

1.3.4 移动端抓包

Android 设备抓包步骤

  1. Fiddler 端:Tools → Options → Connections,勾选 "Allow remote computers to connect"(默认端口 8888)
  2. 查看 Fiddler 所在电脑的 IP:命令行执行 ipconfig
  3. Android 设备设置:
    • 设置 → WLAN → 长按连接的网络 → 修改网络
    • 代理选择"手动",填入电脑 IP 和端口 8888
  4. 浏览器访问 http://电脑IP:8888,下载并安装 Fiddler 根证书
  5. 此时所有手机流量均可在 Fiddler 中查看

iOS 设备抓包注意事项

  • 需要安装 Fiddler 证书并在 "设置 → 通用 → 关于本机 → 证书信任设置" 中开启信任
  • iOS 10.3+ 需要额外添加信任

1.3.5 AutoResponder(自动响应)

用途:将远程资源替换为本地文件,用于调试或绕过前端校验。

python
# 配置步骤:
# 1. 拖拽会话到 AutoResponder 面板
# 2. 勾选 "Enable rules" 和 "Unmatched requests passthrough"
# 3. 选择响应方式:
#    - Find a file...(返回本地文件)
#    - Create New Response(返回自定义响应)
#    - 200-blocking(直接返回空 200)

1.4 爬虫法律风险与 robots.txt

1.4.1 爬虫法律风险

定义:网络爬虫在采集数据时可能触犯的法律法规,主要包括《网络安全法》《数据安全法》《个人信息保护法》和《反不正当竞争法》。

高风险行为(红线)

行为类型法律风险典型案例
绕过登录验证非法获取计算机信息系统数据罪爬取需要登录才能访问的数据
绕过反爬措施破坏计算机信息系统罪恶意绕过 CAPTCHA、IP 封锁
采集个人信息侵犯公民个人信息罪爬取手机号、身份证、地址等
抓取商业竞品数据不正当竞争大规模爬取电商商品价格进行比价
造成服务器过载民事侵权 / 刑事破坏无限制并发导致目标服务器崩溃

安全实践守则

✅ 遵守 robots.txt 协议
✅ 设置合理请求间隔(避免对服务器造成压力)
✅ 只采集公开数据(无需登录即可访问)
✅ 尊重数据的版权和使用条款
✅ 对采集的个人信息进行脱敏处理
✅ 存储数据时添加时间戳和来源标记

❌ 不要爬取需要付费访问的内容
❌ 不要爬取登录后才能查看的用户隐私信息
❌ 不要使用分布式爬虫攻击单一服务器
❌ 不要将爬取数据用于商业竞争

1.4.2 robots.txt 协议

定义robots.txt 是存放在网站根目录的文本文件,告知爬虫哪些路径允许或禁止抓取。

语法规则

# robots.txt 示例
User-agent: *                          # 适用于所有爬虫
Disallow: /admin/                      # 禁止爬取 /admin/ 路径
Disallow: /private/                    # 禁止爬取 /private/ 路径
Allow: /public/                        # 允许爬取 /public/ 路径
Crawl-delay: 10                        # 请求间隔 10 秒

User-agent: Googlebot                  # 仅适用于 Google 爬虫
Disallow: /temp/

Python 中解析 robots.txt

python
from urllib.robotparser import RobotFileParser

rp = RobotFileParser()
rp.set_url("https://www.example.com/robots.txt")
rp.read()

# 检查是否允许爬取
url = "https://www.example.com/private/data.html"
user_agent = "MySpider/1.0"

if rp.can_fetch(user_agent, url):
    print("允许爬取")
else:
    print("禁止爬取")

小结

  1. HTTP 协议是爬虫的基础,理解请求/响应报文结构、方法语义和状态码分类是调试的第一步
  2. HTTPS 通过 TLS 加密保证通信安全,爬虫需要处理证书验证
  3. Requests 的 Session 对象自动管理 Cookie,是模拟登录状态的核心工具
  4. Headers 伪装是绕过反爬的基础手段,User-Agent 和 Referer 最为关键
  5. Fiddler 是抓包调试利器,支持断点修改请求、HTTPS 解密和移动端抓包
  6. 爬虫从业者必须知法守法,尊重 robots.txt,合理控制请求频率

练习

  1. Requests 基础:使用 requests 库请求 https://httpbin.org/get,添加自定义 Headers(User-Agent、Referer),打印返回的状态码和响应头。
  2. Session 登录模拟:使用 requests.Session() 模拟登录流程:先 POST 到 https://httpbin.org/post 提交表单,再 GET https://httpbin.org/cookies 验证 Cookie 是否被自动携带。
  3. Fiddler 抓包实战:启动 Fiddler,用浏览器访问任意网站,在 Fiddler 中找到:
    • 所有图片资源的请求(提示:select image
    • 状态码为 404 的请求
    • 修改其中一个请求的 User-Agent 后放行
  4. robots.txt 分析:访问 https://www.baidu.com/robots.txt,分析其规则,用 urllib.robotparser 检查 https://www.baidu.com/s?wd=test 是否允许爬取。
  5. 异常处理:编写一个带重试机制的请求函数,测试对 https://httpbin.org/status/500 的请求,验证重试 3 次后抛出异常。

Python 学习资料