知其然,知其所以然
爬虫工程 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 真实验证 动画演示
爬虫工程 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 真实验证 动画演示
爬虫工程 2026-10-12

增量抓取:ETag、Last-Modified 与 304

实测条件请求对爬虫增量抓取的作用:200 KB 页面带正确 If-None-Match 得到 304 且响应体 0 字节;100 个页面第二遍,10 个更新,响应体从 19.5 MiB 降到 2.0 MiB;Last-Modified 不变时 304 会错过更新;同一页面重复访问 100 次,max-age 内只需要 1 个请求。

爬虫 增量抓取 ETag Last-Modified 304 条件请求 Cache-Control Python 真实验证 动画演示
爬虫工程 2026-10-12

sitemap.xml:索引文件、gzip 与 lastmod

实测 sitemap.xml 解析:不写 XML 命名空间会解析出 0 条;.xml.gz 文件要自己解压而 Content-Encoding: gzip 由 requests 解开;lastmod 有多种写法,没有 lastmod 的条目不能用来增量;5 万条 URL 用 iterparse 内存 4.0 MiB 对 fromstring 38.5 MiB;lxml 恢复模式会悄悄破坏含 & 的 URL。

爬虫 sitemap sitemap.xml gzip lastmod iterparse lxml XML命名空间 Python 真实验证 动画演示
爬虫工程 2026-10-12

canonical 与重复 URL:同一内容多个地址怎么合并

60 个商品各有 5 种地址加 10 个分页列表页(共 310 个 URL,70 种内容):只规范化 URL 剩 130 组;信任 canonical 61 组但把 10 个不同的分页合成一组;canonical 加内容校验和只看正文哈希都得到正好 70 组;整页字节哈希因为页脚时间戳合并不了(310 组)。

爬虫 canonical 去重 重复URL 内容哈希 rel=canonical Link头 Python 真实验证 动画演示
爬虫工程 2026-10-12

解析器对比:lxml、html.parser、html5lib 如何处理残缺 HTML

以真实 Chrome 154 解析出的 DOM 为标准答案,22 个残缺 HTML 片段:selectolax(Lexbor)和 bs4 + html5lib 22 / 22 一致,html5lib 21 / 22,lxml.html 与 bs4 + lxml 12 / 22,bs4 + html.parser 只有 6 / 22;差别包括是否补 tbody、是否拆开嵌套的 <a>、重复属性取第一个还是最后一个、</br> 是否变成 <br>。

爬虫 HTML解析 lxml html5lib html.parser BeautifulSoup selectolax Chrome 残缺HTML Python 真实验证 动画演示
爬虫工程 2026-10-12

XPath 与 CSS 选择器:表达能力与耗时

在同一个页面上比较 XPath 与 CSS 选择器:16 个选取任务中 CSS 能写 13 个、写不了按文字选/选父元素/选祖先 3 个;XPath 里匹配 class 用 @class="item" 只选到 1 个、contains 多选到 4 个、带空格的写法才与 CSS 的 3 个一致;//a[1] 与 (//a)[1] 差 6 个对 1 个;5000 个 li 的页面上两者耗时都在 2.7–3.1 ms,无稳定差别。

爬虫 XPath CSS选择器 lxml cssselect 选择器 解析 性能 Python 真实验证 动画演示
爬虫工程 2026-10-12

大页面解析:一次性解析与 iterparse 的内存

实测大 HTML 的解析内存:整棵树净增约文件的 11–19 倍(100 MiB 文件 1122–1649 MiB);iterparse 不清理等同整树且更慢(22.63 秒);iterparse 加 clear() 和删前面的兄弟只净增文件的约 1.1 倍(114 MiB),耗时 3.04 秒;给没声明编码的文件要传 encoding,否则「¥」变成「Â¥」。

爬虫 流式解析 iterparse lxml 内存 大页面 html.parser selectolax Python 真实验证 动画演示
爬虫工程 2026-10-12

文本清洗:nbsp、零宽字符、全角半角

实测爬虫文本清洗:nbsp 和全角空格能被 strip/split/\s 处理,零宽空格、BOM、软连字符不能;NFKC 能把全角转半角,但也把 x² 变成 x2、① 变成 1;NFC 与 NFD 的 café 显示一样却不相等;不清洗时正则把「¥12,345」读成 12 而不是 12345。

爬虫 文本清洗 Unicode NFKC nbsp 零宽字符 全角半角 Python 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号