知其然,知其所以然
爬虫工程 2026-10-12

断点续爬:状态存哪、崩溃后丢什么

对真实爬虫进程做 SIGKILL 随机杀死再续爬的实验:只放内存重复抓取平均 112 个;JSON 直接覆盖写 20 次里有 1 次状态文件损坏,原子改名 0 次;SQLite 每个 URL 提交一次重复最多 8 个(在途请求数)、几乎不增加耗时(0.55 对 0.54 秒),而整体重写 JSON 让耗时翻倍(1.12 秒)。

爬虫 断点续爬 SQLite JSON快照 kill -9 持久化 崩溃恢复 Python 真实验证 动画演示
MongoDB 2026-10-12

多文档事务:快照隔离与 WriteConflict

实测多文档事务:事务内读到开始时的快照,事务外的提交看不到;事务之间的写冲突 4 ms 内报 WriteConflict(code 112,带 TransientTransactionError),事务外的写入则等待事务结束(等了 1,526 ms);16 线程 with_transaction 计数 1600 次一个不丢(重试 1,492 次);快照隔离下的写偏斜让在岗人数变成 0。

MongoDB 事务 快照隔离 WriteConflict 写偏斜 with_transaction 真实验证 动画演示
爬虫工程 2026-10-12

优雅停止:收到 SIGINT 时在途请求怎么收尾

实测 asyncio 爬虫收到信号的行为:默认 SIGINT 取消 8 个在途请求(完成 0 个,19 ms 退出);用 add_signal_handler 优雅停止则让 8 个在途请求完成(313 ms),队列剩下的 192 个可保存;SIGTERM 在没有处理器时直接杀死进程;退出用时等于在途请求剩余时间。

爬虫 优雅停止 SIGINT SIGTERM asyncio 信号处理 Python 真实验证 动画演示
爬虫工程 2026-10-12

URL 规范化:大小写、默认端口、片段、参数顺序

实测 URL 规范化对去重的影响:20 组等价写法里 yarl 合并 8 组、w3lib 10 组、自写语法规范化 11 组、再加语义规范化 15 组;1000 个页面 8 种写法共 8000 个 URL,不规范化是 8000 个“不同的”,只做语法规范化 5000 个,加上排序参数、去追踪参数、合并双斜杠后恰好 1000 个。

爬虫 URL规范化 去重 w3lib yarl punycode 查询参数 Python 真实验证 动画演示
爬虫工程 2026-10-12

相对链接解析:urljoin 与 base 标签

用 Node 的 WHATWG URL 对照 Python urljoin:36 个相对链接用例有 11 个结果不同(反斜杠、前后空格、中文编码、大写主机、:80、https:foo 等);urljoin 不过滤 javascript:、file:// 等 scheme;lxml 的 make_links_absolute(resolve_base_href=False) 实测仍应用 <base>;重定向后必须用最终 URL 当 base。

爬虫 相对链接 urljoin base标签 WHATWG URL解析 lxml Python 真实验证 动画演示
爬虫工程 2026-10-12

去重:set 与 Bloom 过滤器的内存和误判率实测

实测 100 万个 URL 的去重结构:set 存完整 URL 128.0 MiB,存 64 位哈希 66.3 MiB,Bloom 过滤器 1% 误判率只要 1.1 MiB;Bloom 实测误判 1.036%(理论 1.004%),加到 3 倍容量时误判升到 43.6%;32 位哈希在 100 万个里就有 127 个撞车。

爬虫 去重 Bloom过滤器 set 内存 误判率 哈希 Python 真实验证 动画演示
爬虫工程 2026-10-12

请求指纹:只哈希 URL 为什么会漏掉 POST 和请求头不同的请求

构造一个响应取决于方法、请求体、Accept-Language 和 Cookie 的本机服务器:180 个请求有 131 种不同的内容;只哈希 URL 去重只拿到 62 种、漏掉 69 种(40 个 Accept-Language 版本、10 个 Cookie 版本、19 个 POST 请求体);把方法、请求体、关键请求头都放进指纹才拿到全部 131 种。

爬虫 请求指纹 去重 POST Accept-Language Cookie Python 真实验证 动画演示
爬虫工程 2026-10-12

SimHash:近似重复页面怎么判定

用合成语料量 SimHash 近似去重:只对正文做时,原文与改 5% 的变体汉明距离中位 4、不相关的两篇中位 18,k=3 召回 47.6%、误报 0;把共用的站点模板一起做,不相关的两篇距离中位降到 6,k=3 误报 37005 对;改用词的 3 元组特征后距离分布整体拉开。

爬虫 SimHash 近似去重 汉明距离 Jaccard 站点模板 去重 Python 真实验证 动画演示
MongoDB 2026-10-12

事务 60 秒上限:到点之后发生什么

实测事务的生命周期上限:默认 60 秒;事务外的写入会等到过期事务被中止(上限调到 5 秒时等了 5,357 ms);过期后继续操作与 commit 都报 251 NoSuchTransaction 且修改回滚;生命周期不因有操作续期;中止不是准点——默认 60 秒的事务 70 秒时仍能提交成功,89 秒才被清理。

MongoDB 事务 transactionLifetimeLimitSeconds NoSuchTransaction 超时 真实验证 动画演示
MongoDB 2026-10-12

事务在 oplog 里长什么样

实测事务在 oplog 里的样子:提交的事务只写 1 条 applyOps 条目(op=c,ns=admin.$cmd),3 个操作装在里面,用 lsid + txnNumber + prevOpTime 链起来;不放进事务则每个操作一条;update 存 diff;提交标记在 config.transactions 的 state: committed;中止的事务不留痕迹;大事务拆成 partialTxn 加一条带 count 的最后条目。

MongoDB 事务 oplog applyOps partialTxn config.transactions 真实验证 动画演示
爬虫工程 2026-10-12

爬虫陷阱:无限日历、会话 ID、参数排列组合

在一个带四类陷阱(无限日历、URL 里的随机 sid、288 种筛选参数组合、相对链接循环)的本机站点上真实抓取:无防御抓 2000 个页面浪费 1738 个;去掉 sid 把预算转给日历陷阱;每个 URL 模板最多 50 个只找到 103 / 263 真实页;放宽到 300 并配合去 sid 和路径重复检测才找到全部且结束。

爬虫 爬虫陷阱 无限日历 会话ID 参数组合 URL模板 去重 Python 真实验证 动画演示
爬虫工程 2026-10-12

分页抓取:offset 与 cursor 在数据变动时漏页、重复

在抓取过程中让数据不断新增和删除:偏移量分页(最新在前)返回 1148 条中重复 148 条,随机删除时漏掉 59 条;最旧在前仍然漏掉 46 条;游标分页和快照分页在新增、删除、新增加删除三种变化下都没有重复也没有漏掉。

爬虫 分页 偏移量分页 游标分页 快照 漏抓 重复 Python 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号