投喂之前把 URL 过一遍,几乎每个做蜘蛛池的人都会做,但多数人只做了一件事:看这个地址能不能打开。存活检测筛掉的是打不开的地址,筛不掉的是另一类问题——同一个目标页,往往能用好几种写法落进入口页。http 与 https、带 www 与不带 www、结尾有没有斜杠、参数顺序换个位置,在浏览器里打开都是同一页,在抓取系统的账本里却是好几条不同的 URL。
这件事为什么值得单独处理
入口页上的链接就是蜘蛛的路线图。如果同一批目标被写成三四种形态,入口页的可点击链接数会被撑大,但真正指向的内容并没有变多。带来的直接结果是:入口页看起来“很丰富”,实际有效线索密度变低;池子里的抓取请求有相当一部分落到了重复地址上;日志里同一目标的抓取记录被拆散,你很难从数字上判断某个 URL 到底被抓了几次。
更麻烦的是后续判断。做冷启动或者调量的时候,很多人是看日志里的抓取条数来判断池子状态的。重复地址混在里面,条数是虚高的,真实覆盖的目标数被高估,后面加量、减量的决策就会失准。
常见的几种“看着不一样其实一样”
协议与主机名
- http:// 与 https:// 写成两条
- 带 www 与不带 www 各写一条
- 用 IP 直接访问与用域名访问混着用
这几种在入口页里最容易被无意中混进来,尤其是从不同来源抓地址拼列表时。建议在投喂前统一到一个形态,通常是站点对外主推的那个版本。
尾斜杠与路径写法
- /page 与 /page/ 同时存在
- /a/./b 与 /a/b
- 路径里出现连续斜杠 //
尾斜杠是否等价取决于服务器怎么处理,有的站点两者都返回 200,页面对蜘蛛来说就是两份。既然不确定,就别把两种都写进去。
大小写与编码
路径部分在多数服务器上是区分大小写的,但参数名、参数值经常不是。同一个中文关键词,UTF-8 编码和 GBK 编码出来的地址完全不同,百分号大小写(%2F 与 %2f)也可能被判成两条。这类地址如果在入口页里同时出现,除了制造重复,还会让蜘蛛抓到一组内容相同的页面。
参数顺序与无意义参数
- ?a=1&b=2 与 ?b=2&a=1
- 带 utm_、from、spm、ref 之类的来源标记
- 带会话 ID、时间戳、随机数
来源标记和会话参数对页面内容没有影响,属于典型该清掉的部分。参数顺序不同但在服务端被忽略的那种,也建议在投喂前统一。
去重放在哪一步
比较顺的顺序是三段:先做归一化,再做存活检测,最后做去重。
- 归一化:统一协议、主机名、大小写、尾斜杠、编码方式,剔除无关参数。这一步只做字符串处理,不请求目标站,成本很低。
- 存活检测:对归一化之后的地址发请求,看状态码和响应内容。这一步才有网络开销,放在归一化之后能少发很多无用请求。
- 去重:按归一化后的完整地址做精确比对,也可以对去掉参数后的路径做一层模糊比对,避免同一个页面换个参数又被当成新地址。
顺序反了会怎样:先存活检测再归一化,等于对同一个页面反复发请求;先存活检测再归一化再存活检测,就更没必要了。
同一目标保留几条地址合适
多数情况下,一个目标页对应一条地址就够了。入口页需要的是明确的线索,不是同一线索的多个副本。下面几种情况可以考虑保留多条:
- 目标站确实同时对外提供 http 和 https,且两者内容独立可访问
- 移动版与桌面版是两套独立地址,并且你打算分别投喂
- 目标页有明确的参数化形式(例如分类筛选页),内容和默认页不同
除此之外,同一目标在入口页里出现多次,基本只是在稀释入口页的链接价值,同时让你后面对日志的分析变难。
几个容易踩的坑
- 只看状态码不看内容:有些站点对不存在的地址也返回 200,配一个提示页。归一化能减少这类地址的生成,但不能替代内容层面的判断。
- 去重粒度太粗:只按域名去重,会把同域下的不同页面当成一条;只按完整地址去重,参数一变又漏了。
- 归一化规则前后不一致:第一周按不带 www 处理,第三周换成带 www,历史日志和现在的数据就对不上了。规则一旦定下来,最好写进流程里固定住。
- 把去重当成收录保障:去重只解决入口页自身的清晰度问题,抓不抓、收不收由目标站和搜索引擎决定,这两件事不要混着看。
落地建议
给入口页做一张固定的处理规则表,把协议、主机名、尾斜杠、大小写、参数白名单这些写清楚,每次投喂前按同一套规则跑一遍。同时保留一份原始地址和归一化后地址的对照,出问题时能回溯是哪一步改的。规则稳定之后,入口页的链接数、日志里的抓取条数才有可比性,后面判断池子状态、调整投喂量才有意义。