news 2026/10/31 16:11:28

搜索引擎蜘蛛抓取路径与抓取预算优化实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
搜索引擎蜘蛛抓取路径与抓取预算优化实战

1. 蜘蛛的入场路线:它到底是从哪扇门进来的

先纠正一个很常见的观察偏差。很多人盯站点的抓取情况,只看一个数字——今天搜索蜘蛛来了多少次。这个数字意义有限,它只告诉你"来过",不告诉你"从哪里来、走了多深、看完之后带走了什么"。真正决定一个站点能不能被有效收录的,是爬行路径的覆盖质量,而不是抓取行为的绝对次数。一只每天来五千次、但只在首页和几个热门列表页之间来回打转的蜘蛛,实际价值远低于一只每天只来三百次、却能把新发布的详情页在半小时内全部走一遍的蜘蛛。

我处理过的抓取异常里,十次有六次根本不是"被惩罚",而是路径被堵死了。新页面挂在第四层分页下面,蜘蛛压根没走到;或者页面正文是脚本异步拼出来的,蜘蛛抓到的 HTML 是个空壳;又或者一堆带参数的筛选链接把待抓队列塞满,新内容排在队尾排了一星期。这些问题从"抓取次数"这个指标上完全看不出来,只有把路径还原出来才看得见。

所以这篇东西想讲清楚两件事:蜘蛛进站的入口是怎么被选中的,以及它进来之后的抓取行为有哪些可以被观测、被引导、被约束的规律。适合正在做站点优化、需要读懂访问日志、或者接手了一个"收录一直上不去"的站点又找不到原因的人。文中给的方法和脚本都可以直接拿去改,日志字段的配置、路径还原的思路、参数收敛的取舍,我都尽量写细。

1.1 入口 URL 的四种来源与它们的权重差异

蜘蛛不是凭空知道你的网址。它拿到 URL 的渠道就那么几类,不同渠道进来的 URL,后续被回访的概率差别非常大。

第一类是主动提交。站点把自己的新 URL 通过资源提交接口推给搜索平台,这类 URL 的抓取优先级通常最高,因为它是"站点自己声明这很重要"。第二类是站点地图文件,蜘蛛定期来拉取,里面的 lastmod 时间是它判断是否需要重抓的重要依据。第三类是外部链接,别的站点指向你的链接,蜘蛛顺着链接爬过来,这类入口的价值在于"外部背书",但可控性最差。第四类是历史抓取记忆,你的页面昨天被抓过,蜘蛛今天会按一个根据更新频率算出来的间隔再来看一眼。

这四类渠道里,最容易被忽视的是第三类。很多站点的外链分布极不均匀,九成的外部链接都指向首页,剩下的一成集中在少数几个老页面上。结果是蜘蛛每次从外链进来,起点永远是首页,然后靠站内链接往下走。站内链接结构一旦有断层,再深的内容就永远见不到光。

提示:不要把"提交了"当成"抓到了"。提交只是把 URL 放进队列,能不能被抓取决于队列里排在你前面的东西有多少。

判断入口质量有个很朴素的观察方法:在访问日志里找出 Referer 为空或者是外部域名的请求,这些就是蜘蛛的"入场点"。统计一下这些入场点的 URL 分布,如果九成都是首页,说明你的入口结构过于单一;如果有相当比例直接落在详情页或栏目页,说明外链和站点地图在起作用。

1.2 链接发现不是单纯的广度优先,而是带打分的队列

网上很多资料说蜘蛛是"广度优先遍历",这个说法只对了一半。早期抓取器确实接近纯广度优先,但现在的抓取器基本都是"优先队列 + 打分"的混合策略。新发现的 URL 不会立刻被抓,而是进入一个待抓队列,队列按分数排序。

分数大致由这几个因素决定:来源页面的质量与抓取频次、锚文本与目标页面的相关性、URL 本身的结构(层级深度、是否含大量参数、路径是否可读)、目标页面历史上的更新频率、以及这个 URL 是否曾经被抓过并返回过有效内容。一个从高质量列表页、用描述性锚文本指向的第 2 层 URL,分数会明显高于一个从页脚、用"更多"指向的第 6 层 URL。

这就解释了一个现象:为什么同一个站点里,有的栏目新内容一发布当天就被抓,有的栏目新内容挂了两周都没动静。不是蜘蛛偏心,是队列分数差太多。

抓取深度的衰减非常陡。我统计过几个内容型站点的日志,从入口算起的点击深度和被访问概率大致是这样一种关系(不同站点差异很大,但趋势普遍存在):

点击深度相对抓取覆盖率典型现象
第 1 层(入口页)接近 100%每次来访必抓
第 2 层(一级栏目/列表)60%–90%高频回访,更新感知快
第 3 层(列表第二页起)30%–60%抓取不稳定,视预算而定
第 4 层(详情页)10%–40%只有热门或强内链的能稳定被抓
第 5 层及更深通常低于 10%大量长期不被发现的页面

这张表最直接的启示是:如果你的重要内容落在第 4 层以下,别指望蜘蛛自己找过去,得靠站点地图、内链改造或者主动提交把路径缩短。

1.3 用日志时间线还原一条完整的抓取链路

单看汇总数据永远找不到根因,必须把某一个蜘蛛会话按时间顺序铺开看。做法很简单:从日志里筛选出来自蜘蛛的请求,按客户端标识分组,按时间排序,看它在几分钟内连续访问了哪些路径、拿到了什么状态码。

一个典型的坏链路长这样(时间、路径、状态码都是我处理过的案例里常见的形态):

  • 10:02:11 抓首页,200,响应 180ms
  • 10:02:13 抓一级栏目页,200,响应 210ms
  • 10:02:14 到 10:02:19 连续抓了 12 个详情页,全部 200,响应 300–800ms
  • 其中 3 个详情页返回 200 但响应体只有 2KB 左右(正常页面 60KB+)
  • 此后 7 天内,这 12 个 URL 中只有 2 个被再次访问

这条链路里最关键的信息不是状态码,是响应体大小。状态码 200 但内容极小的页面,在蜘蛛眼里就是"空页面",它不会报错,但会把这类 URL 的质量分往下调,然后减少回访。这就是所谓的软 404——服务器说"有",实际给的是空壳。软 404 的杀伤力比真 404 大得多,因为真 404 会被蜘蛛标记为失效并从队列移除,软 404 会一直占着队列位置反复浪费预算。

还原链路的时候,一定要把响应时间也带上。响应时间超过 1 秒的页面,在同一个会话里出现多次,蜘蛛的并发会主动收敛;连续几个页面响应超过 3 秒,整个站点的抓取速率会被下调,这个下调不是针对单个 URL,是针对整个站点维度的。

2. 从访问日志读出一只蜘蛛的作息表

没有日志就没有分析,这话不是夸张。搜索平台后台给的数据是聚合后的、有延迟的、经过抽样的,只有服务端原始日志能让你看到每一次请求的完整上下文。但很多站点的日志配置从一开始就不够用——默认格式里没有响应时间、没有响应体大小、没有完整的 UA,等你想分析的时候发现字段缺失,只能等新日志攒够。

2.1 日志字段的最小可用集

至少要有这几项:客户端 IP、请求时间(精确到秒)、请求方法与完整路径(含查询串)、状态码、响应体字节数、User-Agent、Referer、请求耗时。少任何一项,分析就会卡住。比如没有查询串,你就看不出参数爆炸;没有响应体大小,你就发现不了软 404;没有耗时,你判断不了抓取速率被下调的原因。

以常见的 Web 服务软件为例,可以在配置里自定义一个专门给蜘蛛分析用的格式:

log_format spider '$remote_addr - [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" rt=$request_time';

单独开一个日志文件给蜘蛛流量的思路也值得考虑,但我不太推荐按 UA 分流——因为 UA 可以伪造,而且分流规则写错了会漏数据。更稳的做法是全量记录,分析的时候再筛。

日志留存周期也要提前想好。只留 7 天,你只能看到最近一周的抓取行为,做不了同比;想观察一次改版前后的抓取变化,至少要有改版前 30 天和改版后 30 天的数据。磁盘紧张就压缩归档,纯文本日志压缩比很高。

2.2 三重校验判断是不是真蜘蛛

UA 是最不可靠的证据。随便一个脚本都能把 UA 改成蜘蛛的样子,这类伪造流量会把你的统计彻底搞乱。可靠的判断要三个证据叠加。

第一是来源 IP。正规抓取器都有公开的 IP 段,可以做反向解析验证。反向解析出来的域名要能和正向解析对得上,对不上的基本可以判定为伪造。第二是行为特征。真蜘蛛会请求站点根目录下的 robots.txt,会按一定节奏抓取,会在抓取 HTML 之后顺带抓取页面引用的静态资源(渲染阶段)。伪造流量通常不请求 robots.txt,并发很高,只盯着特定路径反复抓。第三是抓取节奏的规律性。真蜘蛛的请求间隔有统计规律,不会出现几毫秒内几十个请求打同一个路径的情况。

我一般用一个简单的过滤链:先按 UA 粗筛,再用 IP 验证,最后用"是否请求过 robots.txt"做二次确认。三步下来误判率很低。

import re from collections import Counter, defaultdict PATTERN = re.compile( r'(?P<ip>\S+) - \[(?P<time>[^\]]+)\] "(?P<method>[A-Z]+) (?P<path>\S+)[^"]*" ' r'(?P<status>\d{3}) (?P<size>\d+|-) "[^"]*" "(?P<ua>[^"]*)" rt=(?P<rt>[\d\.]+)' ) BOT_HINT = re.compile(r'(?i)(spider|bot|crawler)') def load(path): rows = [] with open(path, encoding='utf-8', errors='ignore') as f: for line in f: m = PATTERN.match(line) if not m: continue d = m.groupdict() if not BOT_HINT.search(d['ua']): continue d['status'] = int(d['status']) d['size'] = int(d['size']) if d['size'] != '-' else 0 d['rt'] = float(d['rt']) d['depth'] = d['path'].split('?')[0].rstrip('/').count('/') rows.append(d) return rows def summary(rows): print('请求总数:', len(rows)) print('状态码分布:', Counter(r['status'] for r in rows).most_common()) print('抓取深度分布:', Counter(r['depth'] for r in rows).most_common()) small = [r for r in rows if r['status'] == 200 and r['size'] < 3000] print('疑似软404数量:', len(small)) return small

这段脚本不复杂,但它能在一分钟内把三个关键问题回答掉:状态码有没有异常聚集、抓取深度是不是集中在前两层、有没有大量小体积的 200 响应。软 404 的判定阈值要按站点实际情况调,内容型站点 3000 字节以下基本可以确定是空壳,但如果是接口型页面就得另算。

2.3 抓取频次、并发与响应时间的三角关系

这三个量是互相牵制的。蜘蛛的抓取策略本质上是一个反馈控制:它根据你服务器的响应表现,动态调整抓取速率。响应快,它就提速;响应慢或报错,它就降速。这个机制在很多资料里被忽略,但它解释了大量"抓取量莫名其妙掉了"的现象。

我观察到的经验规律大致是:页面平均响应时间在 200ms 以内,抓取速率能维持在高位;涨到 500ms 左右,速率开始收敛;超过 1 秒,抓取量会有肉眼可见的下降;超过 3 秒,降幅明显。5xx 状态码的影响更直接——连续出现几个 5xx,蜘蛛会立刻降低对整个站点的抓取频率,而且恢复得比降速慢得多,通常要好几天才回到原来的水平。

所以临时性的大促、活动、压测,如果会导致服务器响应变慢,提前在 robots.txt 里对新上线的活动目录做限制,或者给蜘蛛单独做限流,比事后等它慢慢恢复要划算。这个操作我做过几次,效果比想象中明显:活动期间限制抓取,活动结束后放开,抓取量基本能在一两天内回到正常水位;不限制的话,响应时间飙到两三秒持续半天,恢复期要一周以上。

响应表现蜘蛛的典型反应建议动作
平均 < 200ms维持或提升抓取速率保持现状,观察状态码
200–800ms速率轻微收敛排查慢查询、大图、同步外部请求
800ms–2s抓取量下降 20%–50%优先优化列表页和详情页首字节时间
连续 3s 以上全站降频考虑临时限制抓取范围
连续 5xx显著降频,恢复慢紧急修复,不要反复抖动

还有一点值得注意:抓取速率是按"站点"这个维度算的,不是按 URL。所以一个子目录的响应慢,会拖累整个站点的抓取效率。多业务共用域名的时候,这个问题尤其容易踩。

3. 抓取预算:多数站点真正卡住的地方

抓取预算这个词被说得有点玄,其实拆开很简单:你的站点在一段时间内能被抓取多少个 URL,取决于两个量的较小值——服务器能承受的抓取容量,和站点值得抓取的 URL 总量对应的需求。大多数站点的瓶颈不在容量,而在需求侧的构成:一堆不值得抓的 URL 把预算吃掉了,真正需要的页面反而排不上队。

3.1 有效抓取率的计算方式

可以这么理解:有效抓取量 ≈ min(容量, 需求) × 有效比例。有效比例等于"值得抓的 URL 数"除以"实际被抓的 URL 数"。

举个具体的例子。某站点每天被抓 10 万次,其中 3 万次落在各种筛选参数组合页上,2 万次落在分页很深的列表页,1.5 万次是重复的尾斜杠和大小写变体,实际落在有内容详情页上的只有 3.5 万次。有效比例 35%。如果把那些参数页和重复变体收敛掉,同样的抓取容量可以让详情页的抓取量翻倍。这不是理论推演,很多时候做完参数收敛后,新内容的收录速度会有非常明显的变化。

所以诊断抓取预算问题的第一步,是把日志按 URL 模式聚类,看抓取量到底落在哪几类路径上。聚类不用很精细,按路径的第一段、第二段加查询参数的有无来分组就够了。分完组你会发现,通常有两三组路径吃掉了六七成的抓取量,而这几组往往不是你最想被抓的。

3.2 无限空间的几种常见形态

参数组合是最经典的一种。假设一个商品列表页有颜色、尺寸、材质、价格区间、排序方式五个筛选维度,每个维度 4 个取值,理论上能组合出 4 的 5 次方,也就是 1024 个 URL。蜘蛛会把每一个组合都当成独立页面去抓,而它们的内容高度重复。更糟的是这些 URL 之间互相链接,形成一张稠密的网,蜘蛛在里面绕不出来。

分页也是重灾区。列表页翻到第 200 页,内容价值几乎为零,但蜘蛛如果有足够的预算,它真的会一页页翻下去。日历型导航同理,一个日期选择器能生成上万个月份/日期组合的 URL。

会话标识、排序参数、打印页、站内搜索结果页、URL 大小写与尾斜杠变体,这些都属于同一类问题:它们在物理上是不同的 URL,在语义上指向同一个内容。对蜘蛛来说,每一个都要单独抓一次才能确认。

提示:判断有没有"无限空间",就看日志里抓取量最高的 100 个 URL 模式中,是否存在参数组合数量明显超出实际内容量的情况。这个检查半小时能做完。

3.3 收敛手段的选择与它们各自的副作用

手段有几种,效果和副作用差别很大,不能混着用。

手段实际作用适用场景主要副作用
robots 禁止抓取阻止蜘蛛请求这些 URL纯功能页、搜索页、打印页被禁止的 URL 仍可能被索引(只显示 URL 无摘要)
canonical 声明告诉蜘蛛哪个是主版本参数页、变体页、多路径同内容只是建议,蜘蛛可能不采纳
noindex 标记阻止页面进入索引低价值但需要用户访问的页必须允许抓取才能生效
内链 nofollow减少链接权重传递筛选、排序、登录等辅助链接过用会导致正常路径也失去权重
参数配置声明告诉平台哪些参数可忽略有明确参数规律的站点依赖平台支持度,不能完全依赖

最容易踩的坑是 robots 和 noindex 的配合。用 robots 禁止抓取一个页面,同时指望它不被索引,这是行不通的——蜘蛛抓不到页面,就看不到页面上的 noindex 标记,结果可能是这个 URL 以"无摘要"的形式出现在结果里。正确顺序是:先放开抓取、加上 noindex、等页面从索引里消失,再考虑是否要用 robots 屏蔽。这个顺序搞反的站点我见过不少,症状是"搜索结果里有一堆只有标题没有摘要的页面",很难看。

参数页的处理要更细一点。有实际搜索价值的筛选组合(比如"某类目 + 某个主流规格")值得保留并被索引,长尾的、没人搜的组合应该收敛。判断标准不是技术上的,是业务上的:这个组合是否对应真实的搜索需求。没有数据支撑的情况下,保守做法是只让最主流的少数组合可索引,其余全部 canonical 回主列表页。

4. 引导蜘蛛走对路的三个抓手

前面讲的是"不要让它走错",这一节讲"怎么让它走对"。三个抓手按优先级排:内链结构、站点地图、robots 规则。很多人把顺序搞反了,一上来就改 robots,其实内链结构的影响面最大也最持久。

4.1 robots.txt 的能力边界比想象中窄

robots.txt 只做一件事:告诉蜘蛛哪些路径不要请求。它不做索引控制,不做权重控制,也不保证被所有抓取器遵守。语法上支持通配符和结尾锚定,匹配按最长路径优先,这些基础要清楚。

一个实用的写法大概是这样:

User-agent: * Disallow: /search Disallow: /*?sort= Disallow: /*?sessionid= Disallow: /*/print/ Allow: /article/ Sitemap: https://example.com/sitemap.xml

几个细节容易被忽略。一是规则顺序不影响匹配结果,匹配的是最长的那条,不是最先出现的那条,所以不要指望靠顺序来控制优先级。二是Allow的存在是为了在宽泛的Disallow里开洞,比如禁止了整个目录但要放开其中一部分。三是不要在 robots 里写过于宽泛的规则,一个Disallow: /能让整站从索引里消失,而且这类事故恢复起来要几周。四是 robots.txt 本身返回 5xx 的时候,不同抓取器的处理策略不一样,有的会暂停抓取,有的会忽略规则全量抓——所以 robots.txt 必须保证高可用,它不能依赖动态逻辑。

抓取间隔指令的支持度参差不齐,不建议把它当主要控制手段。真想控制抓取速率,靠响应速度和服务器限流更可靠。

4.2 站点地图的价值在于 lastmod 的准确性

站点地图不是"提交了就收录",它的核心作用是告诉蜘蛛"这些 URL 存在,以及它们什么时候变过"。价值全在 lastmod 字段的准确度上。

如果所有 URL 的 lastmod 都是当天,蜘蛛试几次发现时间戳和实际内容对不上,就会降低对这个字段的信任,最后退化成"定期来扫一遍",站点地图的意义就没了。正确的做法是 lastmod 只在内容真实发生实质性变化时更新,页脚的版权年份变了、推荐位换了张图,这些不算。

格式上有硬性限制:单个文件不超过 5 万条 URL、未压缩不超过 50MB,超了要拆分并建索引文件。大站点按栏目拆、按时间拆都可以,拆完之后用一个索引文件指过去。

<?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <url> <loc>https://example.com/article/1001</loc> <lastmod>2024-05-12</lastmod> </url> <url> <loc>https://example.com/article/1002</loc> <lastmod>2024-05-12</lastmod> </url> </urlset>

站点地图里只放返回 200、允许索引、内容完整的 URL。放了 404 或者 noindex 的 URL,会降低整份文件的信任度。这一点在实际操作中特别容易被自动化脚本搞坏——脚本无脑把数据库里所有 ID 都拼进去,不管状态。

4.3 内链层级决定抓取深度上限

内链结构是抓取路径的骨架。判断标准很朴素:从首页出发,点击多少次能到达任何一个内容页。三次以内是比较理想的,超过四次的页面基本要靠其他手段补。

具体怎么改,几个动作最有效:把深层内容通过"最新""热门""相关推荐"模块提升到第 2 层;给列表页做合理的分页深度上限,超出部分用归档页承接;面包屑导航保证每一层都能反向到达;栏目页别做成纯图片或者纯脚本渲染,锚文本要能被解析。

锚文本的分布也值得看一眼。如果全站指向详情页的锚文本都是"点击查看""详情",蜘蛛拿不到任何语义信息,页面质量判断会吃亏。哪怕是自动生成的推荐位,也应该带上标题或关键词。

还有一个隐蔽的问题:同一批内容通过多个路径可达,比如既在"分类 A"下又在"标签 B"下,还通过"专题 C"聚合。这本身没问题,但要注意 canonical 指向一致,否则会形成多条竞争路径,蜘蛛在几个 URL 之间反复横跳,浪费预算。

5. JS 渲染页面的抓取断点

内容靠前端脚本渲染的站点,抓取路径会在一个很特定的位置断掉。这一节把机制说清楚,比反复试错管用。

5.1 两阶段抓取的机制与它的代价

蜘蛛抓一个页面,第一遍拿的是服务器返回的原始 HTML,这时候脚本还没执行,页面里可能只有一个空的容器元素和一堆 script 标签。它先做一次链接发现,把 HTML 里能解析到的链接加进队列。然后,如果这个页面被判断为"需要渲染",它会进入渲染队列,用无头浏览器执行脚本,再抓一次渲染后的 DOM。

关键在于:渲染是额外开销,有独立预算,不是所有页面都会被渲染。首页、重要栏目页、更新频繁的页,被渲染的概率高;深层页面、低质量页面,可能永远不会进入渲染队列。所以"反正蜘蛛会执行 JS"这个假设是危险的。

判断一个页面是否被真正渲染过,有几个可行的观察角度。看日志里有没有页面引用的静态资源请求(渲染时会加载 CSS、JS、图片);看同一个 URL 在短时间内是否有两次抓取记录;看抓取耗时,渲染型抓取的单次耗时会明显高于纯 HTML 抓取。最直接的还是用抓取调试类工具看渲染前后的内容差异。

5.2 内容供应链上的四个断裂点

第一个断裂点是首屏内容依赖异步接口。HTML 里只有一个空 div,数据靠接口返回后填充。如果接口路径被 robots 屏蔽了,渲染阶段拿不到数据,页面就是空的。这个坑配合 robots 规则特别容易踩——为了防止接口被直接索引而屏蔽了整个接口目录,顺带把渲染也废了。

第二个断裂点是路由用哈希。带井号的路径片段不会被当作独立 URL 发给服务器,蜘蛛看到的是同一个基础 URL,所有"页面"在它眼里是一个。

第三个断裂点是交互触发加载。"点击查看更多"才加载的内容,渲染阶段没有点击动作,加载不出来。这类内容要靠分页 URL 或者初始就渲染一批。

第四个断裂点是渲染超时。脚本里有阻塞请求或者死循环,无头浏览器等不到渲染完成就超时退出,抓到的还是空壳。

针对这些,最省事的方案是服务端渲染或预渲染关键页面——至少要保证列表页和详情页的首屏内容在原始 HTML 里就有。做不到的话,退而求其次:给关键页面配静态化的降级版本,通过链接结构把降级版本暴露给蜘蛛。两条路都比"等蜘蛛执行完 JS"可靠。

6. 症状反推:抓取异常的排查链路

排查抓取问题,从症状入手比从理论入手快得多。下面这张表是我自己常用的对照,症状 → 优先怀疑的方向 → 第一步该看什么。

6.1 症状与根因的对照

症状优先怀疑第一步验证
抓取量突然腰斩服务器响应变慢或 5xx 增多按小时统计状态码和平均响应时间
只抓首页不往下走站内链接不可解析或全被 nofollow检查列表页 HTML 里的链接形式
抓取量高但收录极少大量低质 URL 占满预算按 URL 模式聚类抓取分布
页面反复被抓但内容不更新缓存策略或 lastmod 造假看响应头的缓存相关字段、核对 lastmod
新内容几天不被发现入口太深或站点地图未更新检查新页到首页的点击深度
静态资源被大量抓取渲染频繁但页面质量低统计静态资源请求占比
抓取集中在深夜白天响应慢导致降频对比昼夜响应时间曲线

6.2 一次完整的排查链路

拿一个真实场景走一遍:站点改版后第三周,运营反馈新内容收录几乎停滞,抓取总量看起来没怎么变。

第一步,看总量确实没变,但按 URL 模式拆开之后发现,抓取量从详情页转移到了新版块的列表页和它的分页上。新版块上线时加了一个"瀑布流"式的无限滚动,每滚一屏就生成一个新的分页 URL,蜘蛛顺着一直往下翻。

第二步,看这些分页 URL 的状态码,全 200,响应体大小在 40KB 左右,内容重复度极高。这就是典型的无限空间,虽然在物理上不是无限的,但对蜘蛛来说分页数量没有明确上限。

第三步,看详情页的抓取深度。改版后详情页从原来的第 3 层变成了第 4 层,因为新加了一层聚合页。深度增加一层,抓取覆盖率掉了将近一半。

第四步,检查响应时间。改版后列表页加了实时统计接口,同步调用,平均响应从 300ms 涨到 900ms。这解释了为什么抓取速率整体收敛。

四个问题叠在一起:预算被分页吃掉、深度增加、响应变慢、新内容入口变深。修复动作按优先级排:先把实时统计改成异步,响应时间回到 400ms 以内;再给无限滚动的分页加上限,超过 20 屏的内容用归档页承接,并且给分页 URL 加 canonical 指回第一页;然后把聚合页压缩成一层,详情页回到第 3 层;最后把新内容的站点地图更新频率提高到每天,用主动提交补一把。

这套动作做完,第四天开始抓取分布明显变化,详情页占比从 20% 多回到 50% 以上,新内容从发布到被抓的间隔从一周缩短到一天以内。

6.3 几个反复踩到的细节

第一个细节是时区。日志时间、后台数据时间、你自己写脚本用的时间,三者不一致的时候,所有同比分析都是错的。先把时区统一,再谈分析。

第二个细节是假蜘蛛。前面提过,UA 可以伪造,如果不去验证 IP,你可能会为一个根本不存在的"抓取量下降"忙活半天。用"是否请求过 robots.txt"做快速筛选,能过滤掉大部分噪音。

第三个细节是改版要和抓取策略同步改。改版本身会改变 URL 结构和链接形态,如果 robots、站点地图、内链没有跟着调整,就会出现"新版上线、路径断裂"的情况。我的习惯是改版方案定稿时就把这三样列进检查清单,上线前逐项核对。

第四个细节是不要频繁小幅调整。抓取策略的反馈周期是以周计的,今天改一点、明天改一点,日志里全是抖动,你根本判断不出哪个动作起了作用。一次改到位,观察两周,再做下一步。

6.4 一个可以长期跑的小工具

如果想持续观察,写个每天跑的脚本把关键指标存下来比看临时报表有用得多。核心指标不多:总抓取次数、详情页抓取占比、平均响应时间、5xx 比例、软 404 数量、新 URL 首次被抓间隔的中位数。这六个指标每天记一行,一个月后画成趋势图,抓取行为的变化会非常直观。

import csv, datetime from collections import Counter def daily_metrics(rows, prev_seen): total = len(rows) detail = sum(1 for r in rows if r['path'].startswith('/article/')) avg_rt = sum(r['rt'] for r in rows) / total if total else 0 err5 = sum(1 for r in rows if 500 <= r['status'] < 600) / total if total else 0 soft = sum(1 for r in rows if r['status'] == 200 and r['size'] < 3000) fresh = [r for r in rows if r['path'] not in prev_seen] return { 'date': datetime.date.today().isoformat(), 'total': total, 'detail_ratio': round(detail / total, 3) if total else 0, 'avg_rt': round(avg_rt, 3), 'err5_ratio': round(err5, 3), 'soft404': soft, 'new_url_hits': len(fresh), }

脚本本身没什么技术含量,价值在于坚持跑。抓取问题往往是缓慢劣化的,等你在汇总报表里看出来的时候,已经劣化好几周了。

我自己在这件事上踩过的最大的坑,是把"抓取量"当成了健康指标。有一次抓取量稳定增长了两个月,我默认一切正常,结果详情页的抓取占比从 60% 一路掉到 30%,多出来的量全落在了新增的标签聚合页上。等发现问题的时候,一批长尾内容已经三四个月没被更新过了。从那以后,我看抓取数据第一眼永远是结构占比,总量排在后面。路径对了,量自然会跟上;路径错了,量越大浪费越多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/31 16:10:20

OpenClaw本地部署指南:从环境准备到AI应用开发

1. OpenClaw本地部署全景解析OpenClaw作为一款新兴的AI开发工具链&#xff0c;其名称"小龙虾"形象地暗示了它在处理复杂任务时的灵活性和高效性。这个工具链特别适合需要在本地环境中快速搭建、测试和部署AI应用的开发者。与云端服务相比&#xff0c;本地部署能更好地…

作者头像 李华
网站建设 2026/10/31 16:10:20

miniSQL期末大程通关指南:存储引擎、B+树与事务恢复考点精讲

简介&#xff1a;这份资源是浙江大学数据库设计课程的期末大程成果——miniSQL迷你数据库系统&#xff0c;面向正在学习数据库原理、希望动手理解SQL底层实现的高校学生与开发者。压缩包共29个文件&#xff0c;约885KB&#xff0c;以C/C源码为主体&#xff0c;包含9个cpp与9个h…

作者头像 李华
网站建设 2026/10/31 16:09:49

专科开题报告的文献综述只有三篇参考文献够用吗?科迅捷AI(官方网站:www.kexunjie.com)把凑综述的思路说清了

专科开题报告的文献综述&#xff0c;常被问到一个问题&#xff1a;参考文献只有三篇&#xff0c;够用吗&#xff1f;这个问题问的人不少&#xff0c;答法却常常是心虚的——有人赶紧去知网多搜几篇凑数&#xff0c;有人干脆把三篇扩写成五篇&#xff0c;再把每篇摘要抄一段进去…

作者头像 李华
网站建设 2026/10/31 16:09:34

企业级RAG选型决策树:按数据成熟度与响应要求精准匹配

1. 这不是又一篇“RAG框架对比表”&#xff0c;而是一张企业能直接上手的选型导航图最近三个月&#xff0c;我帮六家不同行业的客户做过RAG落地咨询——从制造业设备知识库到金融合规问答系统&#xff0c;从医疗文献辅助检索到政务政策智能解读。每次开场白都一样&#xff1a;“…

作者头像 李华
网站建设 2026/10/31 16:08:26

技术直觉与AI研究:从灵感到学术突破的转化

1. 项目概述&#xff1a;当个人猜想遇上学术规范化 去年冬天的一个深夜&#xff0c;我在笔记本上涂鸦着关于神经网络权重初始化的新想法时&#xff0c;突然在arXiv上看到一篇刚发布的论文——那里面赫然呈现着我过去三个月一直在构思的数学模型框架。这种"自己的直觉被他人…

作者头像 李华
网站建设 2026/10/31 16:07:42

基于YOLOv10的船舶类型识别检测系统设计与优化

1. 项目背景与核心价值船舶类型识别检测系统是海事监管、港口调度、渔业管理等领域的关键技术需求。传统人工观测方式效率低下且容易出错&#xff0c;特别是在恶劣天气或夜间作业时。基于深度学习的自动化识别方案能够实现724小时不间断监控&#xff0c;大幅提升作业效率和准确…

作者头像 李华