豆备 DOUBAK
← 开发日志

豆瓣的封禁页也返回 200

拿 6341 个真实页面校准判定器,以及豆瓣把「我的广播」改名成「我的动态」那天。

一个抓取器最危险的失败方式不是报错,是把错的东西当成对的存下来。 豆瓣把限流页、验证码页、掉登录后的引导页全部用 HTTP 200 返回。 如果只看状态码,你会得到一份「成功抓取了 1157 个页面」的档案, 里面装的是 1157 份「请先登录」。

每一个响应都要有一个判定

所以每个响应都要过一遍分类,产出六种判定之一:

判定意思该怎么办
ok正常页面存下来,继续
blocked被限流/封禁停机,不重试
challenge要过验证码暂停,等人
login会话过期停机(不是可重试的错误)
gone条目已删除记下来,这也是信息
soft404返回了 200 的「没这个页面」按失败处理

判定依据是内容:导航栏里有没有你的用户名、有没有跳到 sec.douban.com、响应体积相对于滚动分布是不是异常、 该有的结构锚点在不在。判不出来的一律算失败—— 没有「大概是对的」这个档位。

封禁页本身也照样写进 WARC。这样以后要重新校准分类器, 不用再抓一次豆瓣,翻旧档案就行。

6341 个页面

作品详情页那条路线的判定描述,是拿一份真实档案里的 6341 个页面校准出来的。 这件事没法在设计阶段做——十五年跨度的豆瓣页面结构差异很大, 坐在屋里想出来的锚点,碰上 2011 年的页面就碎了。

豆瓣把「我的广播」改名了

同一天撞上的:广播页的标题从「我的广播」变成了「我的动态」, 而它正好是那条路线的结构锚点之一。于是整条最高优先级的路线一夜之间全部判成失败。

这个事故本身是设计生效的证明——判定是「失败」而不是「抓到了空数据」, 所以它响了,而不是静静地产出一份空档案。但它也说明锚点的选择要挑 结构性的东西,别挑文案。文案是产品经理的,随时会变。

个人主页不能当事实来源

还有一个同类的:一开始判定和「豆瓣声称有多少条」都是从个人主页上读的。 问题是个人主页是用户可自定义的——分类区块可以隐藏、可以调顺序, 某个类别可能根本不显示。这意味着两件事:判定不能依赖那些区块的存在, 声称数量也不能从那里取。

改成从每一个列表页自己的标题读,比如 <h1>我看过的影视(1333)</h1>。 这个数字必须在抓的当下就记下来,因为它事后不可重建—— 当然,它能证明的东西比看上去少,那是 另一篇的话题。

← 更新:一堆档案不等于一条链 更早:豆瓣自己报的数量不能用来证明抓全了 →