返回博客

解析器返回空字段,代理无关:修复布局漂移问题

解析器返回了空值,你更换了代理——但问题出在网站的重新设计上。我们来分析一下,如何在五分钟内区分封禁和布局漂移,Scrapling 的自适应选择器是如何工作的(在 SQLite 中的元素指纹和相似性搜索耗时 2.46 毫秒),以及为什么基准需要从你之后收集数据的相同地理位置进行拍摄。

📅2026年9月5日
解析器返回空字段,代理无关:修复布局漂移问题

解析器运行了半年,而今天数据库中出现了空行。第一反应是——被封了,需要更换代理。更换代理池,提高IP质量,支付住宅IP而不是数据中心IP——但字段仍然是空的。因为原因不在于封锁:网站迁移到了新的布局,而你的CSS选择器不再适用。

这是最昂贵的故障类型,因为它保持沉默。封禁是显而易见的:403、验证码、重定向。布局漂移不会导致任何错误——HTTP 200,页面已获取,流量已支付,而输出却是None。我们来看看如何在五分钟内区分这两者,以及如何在每次重新设计后停止手动重写选择器。

谁需要这个

这是给那些在生产环境中运行解析器超过一个冲刺的人:监控竞争对手价格、收集评论、聚合职位、每日分析导出。如果你只运行一次脚本然后丢弃——布局漂移与你无关。如果脚本在cron中运行数月,这是你支持的主要开支。

问题的规模并非虚构。根据GroupBWT分析师的评估,网站的不可控结构变化大约占40-60%的重复支持成本,在大型项目中。某些行业中10-15%的爬虫每周需要修复——由于DOM的偏移、指纹识别和端点的限流。也就是说,修复选择器的成本与绕过反机器人系统的成本相当,但关注度却少得多。

背景并不乐观:在Apify的《2026年网络抓取状态》报告中,65.8%的受访者增加了代理的使用,58.3%的人表示代理费用逐年增长,而超过62%的人则表示基础设施成本整体上升,主要是由于对机器人的保护加强。在这种情况下,浪费支付的流量在那些你根本无法提取数据的页面上——令人更加沮丧。

步骤1. 区分封禁与布局漂移

诊断只需几分钟,并且必须严格按照顺序进行——否则很容易“修复”错误的故障。

  1. 查看响应代码和主体大小。 403、429、503,重定向到检查页面或2-5 KB的主体——这是反机器人。HTTP 200和200-800 KB的完整页面——网站允许你访问,问题不在于代理。
  2. 将原始HTML保存到磁盘并用眼睛打开。 不是在调试器中,而是在浏览器中。如果商品/评论/价格在,解析器却看不到——这是布局漂移。
  3. 在文件中搜索所需文本。 如果在HTML中存在,但通过你的选择器无法访问——标记已更改。如果完全不存在——内容通过脚本加载,需要浏览器引擎,而不是HTTP请求。
  4. 与之前成功的导出进行比较。 对同一URL的旧HTML和新HTML进行差异比较:通常可以立即看到新的包装类、迁移的块或将id替换为data-*
  5. 检查网站是否提供了不同版本的页面。 这个问题稍后会单独讨论,因为在这里代理确实有关系。

如果在第三点后诊断为“标记已偏移”,更换代理是毫无意义的。需要一个能够找到元素的解析器,即使选择器已经过期。

步骤2. 什么是自适应选择器

这个想法很简单:与其死死绑定到.product-card > h3.title这行,不如库一次性记住所需元素的“肖像”,在下次运行时寻找页面上与这个肖像最相似的元素。

Scrapling中,这个实现是最实用的——这是卡里姆·肖阿伊尔的开源Python框架。该项目于2024年10月发布,到2026年9月在GitHub上获得了超过78,000个星标;截至撰写时的最新版本是v0.4.15,2026年8月23日,提交每天都在进行。需要Python 3.10+。

自适应搜索的机制是这样的。当你调用选择器并设置auto_save=True时,Scrapling会保存元素的指纹:

  • 标签名、文本和所有属性及其值;
  • 邻居的标签名;
  • 到元素的路径——仅通过标签名;
  • 父级的标签、属性和文本。

指纹存储在本地SQLite数据库中,并通过“域名 + 标识符”进行键控。域名来自页面的URL(或通过adaptive_domain参数设置),默认标识符是选择器的字符串——如果传递identifier=,则可以使用你自己的标识符。

当布局发生变化,普通选择器返回空值时,调用adaptive=True会提取保存的指纹,并对页面上的所有元素进行处理,计算模糊相似度——甚至包括属性的顺序。返回相似度最高的元素。

这非常便宜。根据项目的官方基准,解析时间为1.99毫秒,而Parsel/Scrapy为2.01毫秒,PyQuery为22.93毫秒,Selectolax为80.57毫秒,BeautifulSoup与lxml为1541毫秒。自适应搜索相似元素的时间为2.46毫秒,而AutoScraper为13.3毫秒。也就是说,针对重新设计的保险在网络延迟数百毫秒的背景下,增加的请求时间大约为两毫秒。

步骤3. 安装和启用

安装取决于你是否需要浏览器:

  1. pip install scrapling——仅解析器,没有网络部分。如果你通过自己的代码获取HTML,这就足够了。
  2. pip install "scrapling[fetchers]",然后scrapling install——添加提取器并下载带有依赖项的浏览器。
  3. 附加选项:[ai]——MCP服务器,[rag]——RAG的包装,[shell]——交互式控制台,[all]——全部。还有现成的镜像pyd4vinci/scrapling

接下来是两次运行。第一次在实时工作布局上保存指纹,第二次已经能够承受重新设计:

  1. 基准运行。 创建一个Selector对象,设置adaptive=True,并务必传递url——否则域名将移入键"default",不同网站的指纹将混合。调用所需的选择器并设置auto_save=True
  2. 实际运行。 使用相同的选择器,但设置adaptive=True。当布局完好时,将使用普通路径。当出现故障时,将启用相似性搜索。
  3. 记录差异。 当普通选择器返回空值,而自适应选择器找到内容时——这是“网站迁移”的信号,必须在监控中看到,而不是默默吞下。

关于重写的重要细节:保存不会累积。对同一对“域名 + 标识符”的重复auto_save将覆盖之前的指纹。因此,基准指纹应在已知正确的页面上拍摄,而不是在整个URL池的循环中。

步骤4. 代理:它们到底有什么关系

我们开始时提到布局漂移与代理无关。这是对的,只有一半,而另一半是需要花钱的。

网站可能会因为代理的原因给你不同的标记。 地区、语言和国家会改变页面模板:不同的块顺序、不同的类、不同的价格和日期格式。这不是假设——在Scrapling中有一个典型的修复:在版本0.4.12中,StealthyFetcher移除了强制的区域设置en-US,因为强制的区域设置与实际地理位置不符,导致行为异常。因此,工作规则是:从与你收集数据相同的地理位置拍摄基准指纹。通过德国IP拍摄的指纹将与通过巴西IP获取的页面匹配度较低——你将收到“网站更改布局”的错误警报。

实际后果:

  • 如果代理池是多国的——通过adaptive_domain分隔指纹,将“域名 + 国家”作为键。否则,SQLite中的一条记录将不断被来自不同地理位置的版本覆盖。
  • 对于长脚本,保持一个国家和一个会话用于整个任务。如何实现这一点,在关于粘性会话及其使用时机的材料中有详细讨论。
  • A/B测试和渐进式发布在同一域名上同时提供两个实时布局。在这里,自适应搜索尤其有用:它将从两个分支中提取元素,而严格选择器将在一半请求中随机返回空值。

在Scrapling中可以在所有级别设置代理。对于快速HTTP请求,FetcherAsyncFetcherproxies参数。对于会话,有ProxyRotator,它接受地址列表——将其插入到FetcherSession中。浏览器的DynamicSessionStealthySession在会话级别接受代理,以便IP在脚本中间不会更改。

在版本0.4.12中出现的另一项节省代理池和神经的功能是AutoThrottle:库会根据服务器的响应自动调整请求之间的暂停,在封禁时加倍延迟,并尊重Retry-After头。这正是将细致的抓取与因天真的重试而导致的封禁加速区分开的行为。

潜在问题

  • 不要将带有指纹的SQLite提交到git。 文档对此有明确警告。同时,不要在包含个人数据的页面上使用auto_save——指纹中会包含元素的文本和属性。
  • 自适应搜索不是监控的替代品。 它将返回“最相似”的元素,而最相似的并不总是正确的。如果网站将折扣价和非折扣价的位置互换,相似度很高,但数据却是错误的。保持对值范围和导出中空字段比例的检查。
  • 静默故障比响亮故障更昂贵。 当选择器默默返回None时,管道继续在页面上运行并消耗支付的流量。关于未提取数据的千兆字节实际成本的详细分析——为什么每GB的代理费用不准确
  • 指纹会过时。 在确认重新设计后,重新拍摄基准指纹,否则下次网站的更改将被视为过时的肖像,准确性将下降。
  • 如果HTML中根本没有内容——自适应性无济于事,需要浏览器提取器。在0.4.15中,浏览器标签在请求之间得以重用,close_pages()方法强制关闭它们;同时修复了无头模式下的挂起问题,Turnstile的解决方案不再依赖于浏览器的区域设置。

在这种任务中选择什么类型的代理

选择不是由解析器决定的,而是由目标网站决定的:

  • 数据中心代理——用于没有严重反机器人系统的网站:文档、政府注册、开放目录、RSS和CSV馈送(对于后者,在0.4.13中添加了XMLFeedSpiderCSVFeedSpider,并自动解压gzip)。便宜且快速,通常标记的稳定性更高。
  • 住宅代理——用于市场、聚合器和所有根据地理位置个性化结果的内容。在这里,拍摄基准并从一个国家收集数据是至关重要的,否则你将修复的不是故障,而是你自己的地理位置。
  • 移动代理——当网站提供移动模板并需要按原样解析,或者当对IP的信任比每GB的价格更重要时。

简而言之

导出中的空字段是两个不同的诊断,具有不同的治疗方案。首先检查响应代码和原始HTML:如果页面完整到达,则无需更换代理,问题在于标记漂移。Scrapling的自适应选择器在请求中以几毫秒的速度解决了这一类故障——在工作布局上保存指纹,在实际运行中启用adaptive=True并记录触发时刻作为重新设计的信号。并保持地理位置稳定:一半“突发重新设计”在实践中被证明是由于语言版本的变化,因代理更换而导致。

如果稳定的地理位置和可预测的会话正是你的解析器所缺乏的,请查看ProxyCove的住宅代理:选择国家、粘性会话和按实际使用的流量付费。