很多人调试蜘蛛池入口页时,盯着页面 HTML 看半天,却忽略了更早被蜘蛛读到的东西——HTTP 响应头。蜘蛛请求一个 URL,服务器先返回响应头和状态码,之后才是正文。头部信息如果配置得别扭,蜘蛛可能还没解析到链接就已经做了判断。
响应头在抓取链路里的位置
蜘蛛的工作顺序大致是:发请求、收响应头、判断状态码与内容类型、决定是否下载正文、解析链接。响应头处在“决定要不要继续”的位置,它的作用往往比入口页里多写几行文字更靠前。
常见需要留意的头部有:content-type、last-modified、etag、cache-control、content-encoding、vary、x-robots-tag,以及跳转时的 location。
Content-Type 与字符集:别让蜘蛛以为这是个文件
入口页返回的应该是 text/html,并带上明确的字符集,例如 content-type: text/html; charset=utf-8。如果服务器把入口页返回成 application/octet-stream、text/plain,或者干脆没有 charset,蜘蛛可能把它当成下载文件,或无法确定编码,链接解析自然受影响。
- HTML 页面:text/html; charset=utf-8
- 纯文本 sitemap:application/xml 或 text/xml
- 不要用 text/plain 返回真正需要解析链接的入口页
字符集最好和页面里的 meta charset 保持一致,避免出现头部说 utf-8、正文里却是 gbk 这种自相矛盾的情况。
Last-Modified 与 ETag:告诉蜘蛛“这次不用重爬”
这两个头部直接关系到蜘蛛会不会走 304 流程。入口页内容没变时,服务器返回 304 Not Modified,蜘蛛就知道可以复用已有内容,减少下载量。这对蜘蛛池这种页面数量多的场景挺有用:抓取预算省下来,可以分给更多待发现的 URL。
反过来,如果入口页每次请求都返回 200 和全新的 last-modified,蜘蛛无法判断内容是否变化,可能反复下载同一批页面。要避免“每次都假装更新”的写法。
Cache-Control:别把蜘蛛挡在缓存外面
入口页往往套了 CDN 或反向代理,cache-control 决定缓存多久、谁来缓存。这里容易出两个问题:
- 缓存时间过长:入口页的链接列表更新了,CDN 还在返回旧版本,蜘蛛拿到的和实际不符。
- no-store 或 no-cache 乱用:本来想让内容即时更新,结果节点频繁回源,入口页响应变慢,又回到抓取效率的问题上。
比较稳妥的做法是给入口页设置较短的缓存时间,并在链接列表变动时主动刷新缓存,而不是长期缓存或完全禁用缓存。
几个容易被忽略的头部
X-Robots-Tag
它在响应头里承担和 meta robots 类似的作用。如果不小心给入口页加了 noindex 或 nofollow,页面里的链接可能就不被跟进了。配置 CDN、安全插件或网关时,留意它们是否悄悄加了这个头。
Vary 与 Content-Encoding
如果服务器根据 User-Agent 或 Accept-Encoding 返回不同内容,vary 要写清楚,否则缓存层可能把移动版内容返回给桌面蜘蛛,或者反过来。压缩本身没问题,但要让蜘蛛能正常解压。
Location
跳转时 location 指向的目标要可访问,不要链条太长。跳转层级过深,蜘蛛跟到一半就停了,这在入口页里等于白铺。
怎么自查
- 用 curl -I 或浏览器网络面板看响应头,先确认状态码和 content-type。
- 连续请求两次,观察第二次是否返回 304,last-modified 和 etag 是否稳定。
- 检查 CDN 回源配置,确认入口页没有被长期缓存或错误缓存。
- 核对是否有意外的 x-robots-tag,尤其是经过网关和安全组件之后。
响应头是蜘蛛对入口页的第一印象。它不直接决定链接会不会被发现,但会影响蜘蛛愿不愿意继续读下去、愿不愿意下次再来。
把响应头理顺,成本不高,却能减少很多“页面明明写好了,蜘蛛却没动静”的困惑。蜘蛛池本身只解决 URL 发现的一环,头部配置属于把这一环做扎实的细节,剩下的收录和排名仍要看目标页自身。