进阶与最佳实践
爬虫写到一定程度,拼的不是"能跑",是稳、快、不被封。这章讲工程化经验。
分布式爬虫
去重与断点续爬
论怎么不重复爬
集合去重:已爬 URL 存 set,内存够就行。Redis 去重:大规模用 Redis set,跨进程共享。布隆过滤器:URL 上亿时用,省内存。断点续爬:爬一半崩了,把已爬 URL 存文件/Redis,下次从断点继续。
增量爬取
论怎么只爬新内容
时间戳法:记录上次爬到的最新文章时间,下次只爬比这个新的。哈希法:把文章内容算个 MD5,存下来,下次先比对再决定爬不爬。URL 去重:已爬 URL 存 Redis/文件,遇到跳过。增量爬取是监控类爬虫的核心——每天跑一次,只入库新内容。
布隆过滤器:亿级 URL 去重
爬虫项目结构规范
API 优先原则
论能调 API 就别爬 HTML
现代网站的后端 API 返回结构化 JSON,比爬 HTML 快 10 倍、稳 100 倍。打开 DevTools Network,找 XHR/Fetch 请求,看哪个接口返回了你要的数据。直接调那个接口,省得解析 HTML 还能跳过前端反爬。找接口 > 爬 HTML > Selenium,优先级从高到低。
遵守 robots.txt
分布式爬虫:Scrapy-Redis
论什么时候要分布式
单机爬几万页面够了。但要爬几十万、上百万,单台机器带宽和CPU都顶不住。Scrapy-Redis 把请求队列放 Redis,多台机器跑同一个 spider,共享队列、共享去重,一台挂了另一台接着爬。这是工业级爬虫的标配。
编码问题怎么排查
数据质量验证
论爬完不等于爬对
行数对不对:预期 250 条,实际多少条?空值多不多:评分/标题有没有空?抽样看几条:随机抽 5 条手动对一下原网页。去重:有没有重复 URL。数据爬完先验证,别急着入库分析。
日志与异常处理
限流策略:别打挂对方
| 策略 | 怎么做 |
|---|---|
| 固定间隔 | time.sleep(1),简单但容易被识别 |
| 随机间隔 | time.sleep(random.uniform(1, 3)),更像人 |
| 令牌桶 | 每秒最多 N 个请求,平滑 |
| Semaphore | 异步并发限流,同时最多 N 个 |
数据清洗
重试逻辑:失败自动重试
常见坑
| 坑 | 怎么避 |
|---|---|
| 编码乱码 | 中文网站有时是 GBK,resp.encoding = "gbk" 或看 resp.apparent_encoding。 |
| HTML 不规范 | 用 lxml 解析器,比 html.parser 容错好。 |
| 动态内容抓不到 | HTML 里没数据?开 DevTools Network 找 JSON 接口。 |
| 被封不知道 | 检查 status_code,403/429 要换代理/降速。 |
| Cookie 过期 | 定期重新登录,或用 Session 保持。 |
| HTML 结构变了 | 网站改版,选择器失效。定期检查,选择器写稳一点。 |
| 没存 Cookie 就翻页 | 第一页能看第二页 403。用 Session 保持。 |
| 没设超时 | 对方不响应,程序永远挂着。必须 timeout。 |
数据量与带宽预估
论爬之前先算笔账
一页 100KB,爬 1 万页 = 1GB 流量。100 个并发、每个 1 秒返回 = 100 秒爬完。但对方服务器扛不扛得住?你家带宽够不够?先小批量试,再放量,别一上来就并发 1000。
新手最常犯的 5 个错
| 错 | 后果 |
|---|---|
| 不设 timeout | 程序永远挂着 |
| 不设请求间隔 | 秒被封 IP |
| 不带 User-Agent | 403 拒绝 |
| 不看状态码 | 404 还在那解析 |
| 乱爬敏感数据 | 法律风险 |
| 不做去重 | 同一条数据爬 N 遍 |
| 不存断点 | 爬一半崩了从头再来 |
| 不查状态码 | 403 了还以为是自己解析错 |
| 不设 Referer | 防盗链网站直接 403 |
| 不分页只爬第一页 | 漏了 90% 数据 |
| 编码不对存 CSV | Excel 打开乱码 |
| 不处理重定向 | 301 后丢 Cookie |
| 不设重试 | 一次失败就跳过 |
| 不验证数据 | 爬了一堆空值不知道 |
| 不写日志 | 跑崩了不知道哪错了 |
| 不分模块 | 一个文件 1000 行没法维护 |
| 不管编码 | 中文全是乱码 |
| 不更新代码 | 网站改版了还按老选择器爬 |
| 不试小批量 | 一上来就 1000 并发 |
| 不存原始 HTML | 解析错了没法回头查 |
| 不做监控 | 爬虫挂了几天不知道 |
推荐学习资源
论学爬虫去哪学
官方文档:requests / BeautifulSoup / Scrapy / Playwright 官方文档都很全,是第一手资料。DevTools:所有反爬手段的答案都在浏览器 F12 里。动手:找个公开 API 站(如 httpbin.org)先练手,别一上来就爬真实站。
爬虫工具生态一览
| 工具 | 什么时候用 |
|---|---|
| requests | 入门、少量请求、调 API |
| aiohttp | 异步并发,几百上千个请求 |
| BeautifulSoup | 解析 HTML,入门友好 |
| lxml | 解析 HTML,快,XPath |
| Selenium | 动态页面、必须登录、模拟浏览器 |
| Playwright | 现代浏览器自动化,比 Selenium 稳 |
| Scrapy | 工程化爬虫,整站爬 |
| Scrapy-Redis | 分布式爬虫,多机协作 |
1.(概念题)requests 和 aiohttp 的本质区别?
答案
requests 同步阻塞,发一个等一个;aiohttp 异步,一个线程挂起几百个请求同时飞。IO 密集型 aiohttp 快 10 倍以上。
2.(概念题)什么是 robots.txt?必须遵守吗?
答案
网站根目录的规则文件,写了哪些路径不让爬。不是法律,是君子协定。尊重它,别爬 Disallow 的路径。
3.(概念题)Scrapy 的 Pipeline 什么时候用?
答案
数据清洗、去重、存数据库时。Spider 只管提取,Pipeline 管存储,职责分离。
4.(概念题)为什么用 Semaphore 限并发?
答案
无限制并发会把对方服务器打挂、自己被封 IP。Semaphore 限制同时最多 N 个请求,既快又礼貌。
5.(概念题)被封 IP 了怎么办?
答案
换代理池、降速、换 UA、加 Cookie 池。先搞清楚是临时封还是永久封,别一上来就换代理。
6.(概念题)动态渲染页面怎么抓数据?
答案
① 找后端 JSON 接口(最推荐);② Selenium/Playwright 模拟浏览器渲染;③ 逆向 JS 加密参数。
7.(概念题)怎么处理验证码?
答案
简单验证码用 ddddocr/tesseract;复杂的用打码平台(人工识别)。别自己写模型训,不划算。
8.(概念题)什么是增量爬取?
答案
只爬新内容,不重复爬。用时间戳/哈希判断"这篇上次爬过没"。常用于监控类爬虫。
9.(代码题)怎么下载一张图片?
答案
r = requests.get(img_url); open("a.jpg","wb").write(r.content)。用 content 字节,不是 text。
10.(概念题)HTML 解析用 BS4 还是 XPath?
答案
入门小脚本 BS4 直观;大规模用 lxml+XPath 快 3-10 倍。功能上能互相替代。
11.(概念题)爬虫怎么存 Cookie?
答案
requests.Session() 自动内存里存;要持久化用 LWPCookieJar 存文件。aiohttp 用 CookieJar。
12.(概念题)什么是中间件?Scrapy 中间件干嘛用?
答案
Downloader Middleware 在请求发出前/响应回来后插一脚:加 UA、换代理、重试。Spider Middleware 在解析前后插一脚。
13.(概念题)为什么别爬登录墙后数据?
答案
未授权访问,法律风险。要么用自己账号按规矩用,要么找公开数据。
14.(代码题)怎么设置超时?
答案
requests.get(url, timeout=10)。不设超时程序会永远挂着。
15.(思考题)API 优先原则是什么?
答案
"能调 API 就别爬 HTML"——API 返回结构化 JSON,稳定、快、不依赖页面结构。先找后端接口,找不到再爬 HTML。