1. 开篇:为什么需要伪装与会话?
作为一名爬虫开发者,我经常遇到这样的场景:明明代码逻辑没问题,但就是拿不到想要的数据。后来才发现,大多数网站都会检测请求是否来自真实浏览器。这就是为什么我们需要学习伪装和会话管理——让我们的爬虫看起来更像人类用户。
记得刚开始做爬虫时,我直接用裸奔的Requests发请求,结果要么被拒绝,要么被限流。直到学会了设置请求头和会话管理,爬虫才真正"活"了起来。今天,我就把这些实战经验分享给你。
2. HTTP请求头详解
2.1 请求头的作用原理
请求头(Headers)是HTTP请求的重要组成部分,它告诉服务器关于客户端的信息。没有合理设置请求头的爬虫,就像没穿衣服走在街上一样显眼。
服务器通常会检查这些关键字段:
- User-Agent:客户端类型和版本
- Accept:客户端能接收的内容类型
- Referer:请求来源页面
- Cookie:会话标识
提示:现代网站通常会有多层防护,仅设置User-Agent可能不够,需要完整的请求头组合。
2.2 实战:获取真实浏览器请求头
最可靠的方法是直接从浏览器复制请求头:
- Chrome中按F12打开开发者工具
- 访问目标网站
- 在Network标签找到任意请求
- 右键选择Copy → Copy request headers
得到的格式类似这样:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Accept: text/html,application/xhtml+xml Accept-Language: zh-CN,zh;q=0.9 Referer: https://example.com/2.3 在Python中设置请求头
headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)', 'Accept': 'text/html,application/xhtml+xml', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Referer': 'https://example.com/' } response = requests.get('https://target.com', headers=headers)3. User-Agent的高级使用技巧
3.1 常见User-Agent类型
不同设备的User-Agent差异很大:
- PC端Chrome:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) - 移动端Safari:
Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) - 旧版IE:
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
3.2 随机User-Agent实现
固定User-Agent容易被识别,建议使用随机轮换:
from fake_useragent import UserAgent ua = UserAgent() random_ua = ua.random headers = {'User-Agent': random_ua}注意:fake-useragent需要单独安装:
pip install fake-useragent
4. Session会话管理实战
4.1 为什么需要Session?
普通请求是无状态的,而Session可以:
- 自动处理Cookie
- 保持TCP连接复用
- 共享请求配置
- 维持登录状态
4.2 基础Session用法
s = requests.Session() # 首次请求会设置Cookie s.get('https://example.com/login') # 后续请求自动携带Cookie response = s.get('https://example.com/dashboard')4.3 封装高级Session类
我推荐封装一个SmartSession类:
class SmartSession: def __init__(self): self.session = requests.Session() self.headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)', 'Accept-Language': 'zh-CN,zh;q=0.9' } def get(self, url, **kwargs): return self.session.get(url, headers=self.headers, **kwargs) def post(self, url, data=None, json=None, **kwargs): return self.session.post(url, data=data, json=json, headers=self.headers, **kwargs)5. 合规处理登录与Cookie
5.1 手动获取Cookie方法
- 使用浏览器正常登录目标网站
- 按F12打开开发者工具
- 在Application → Cookies中找到有效Cookie
- 复制到爬虫代码中:
cookies = { 'sessionid': 'abc123...', 'csrftoken': 'xyz456...' } response = requests.get(url, cookies=cookies)5.2 表单登录实现
对于简单登录表单:
login_data = { 'username': 'your_username', 'password': 'your_password' } s = requests.Session() s.post('https://example.com/login', data=login_data) # 现在s已保持登录状态 response = s.get('https://example.com/protected')6. 反爬机制与应对策略
6.1 常见反爬手段
| 反爬类型 | 检测方式 | 应对方法 |
|---|---|---|
| UA检测 | 检查User-Agent | 使用真实浏览器UA |
| Referer检查 | 验证来源页面 | 设置合理Referer |
| 频率限制 | 统计请求频率 | 添加随机延迟 |
| Cookie验证 | 检查会话Cookie | 使用Session保持状态 |
6.2 请求频率控制
避免被封的关键是模拟人类行为:
import time import random def random_delay(): time.sleep(random.uniform(1, 3)) # 1-3秒随机延迟 for page in range(1, 10): response = requests.get(f'https://example.com/page/{page}') random_delay()7. 实战案例:完整爬取流程
7.1 准备工作
- 安装必要库:
pip install requests fake-useragent- 准备目标网站分析:
- 确定数据所在URL
- 检查需要的请求头
- 确认是否需要登录
7.2 完整代码实现
from fake_useragent import UserAgent import requests import time import random class BookSpider: def __init__(self): self.ua = UserAgent() self.session = requests.Session() def get_random_headers(self): return { 'User-Agent': self.ua.random, 'Accept': 'text/html,application/xhtml+xml', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Referer': 'https://book.douban.com/' } def crawl_page(self, page): url = f'https://book.douban.com/top250?start={page*25}' headers = self.get_random_headers() try: response = self.session.get(url, headers=headers) response.raise_for_status() return response.text except Exception as e: print(f"请求失败: {e}") return None def run(self): for page in range(10): html = self.crawl_page(page) if html: # 这里添加解析逻辑 print(f"成功获取第{page+1}页数据") # 随机延迟 time.sleep(random.uniform(1, 3)) if __name__ == '__main__': spider = BookSpider() spider.run()8. 常见问题与解决方案
8.1 请求被拒绝(403)
可能原因:
- User-Agent被识别为爬虫
- 缺少必要请求头
- IP被暂时封禁
解决方案:
- 检查并完善请求头
- 添加Referer等必要字段
- 更换IP或等待一段时间
8.2 登录状态不保持
可能原因:
- 没有使用Session
- Cookie过期
- 网站有额外验证
解决方案:
- 确保使用requests.Session()
- 检查Cookie有效期
- 模拟完整的登录流程
8.3 数据获取不完整
可能原因:
- 数据是JavaScript动态加载
- 需要特定请求参数
- 分页逻辑有误
解决方案:
- 检查Network中的XHR请求
- 分析页面加载逻辑
- 验证分页参数
9. 高级技巧与优化建议
- 请求头轮换:不只是User-Agent,其他头信息也可以定期更换
- IP代理池:对于严格网站,需要考虑使用代理IP
- 浏览器指纹模拟:一些网站会检测浏览器指纹特征
- 请求间隔随机化:更自然的访问间隔能降低检测概率
- 错误重试机制:对临时性错误实现自动重试
一个带重试的请求示例:
def safe_request(url, max_retry=3): for i in range(max_retry): try: response = requests.get(url, timeout=10) return response except Exception as e: print(f"请求失败({i+1}/{max_retry}): {e}") time.sleep(2**i) # 指数退避 return None在实际项目中,我发现最有效的策略是尽可能模拟真实用户行为。不要追求极致的速度,稳定性和可靠性才是长期运行的关键。对于重要项目,建议实现完善的日志系统和监控机制,能够及时发现和处理异常情况。