政策快报平台上线第一天,爬虫系统很简单:一台服务器,跑着几个Python脚本,定时去十几个网站抓取政策信息。每天能抓几百条,够用了。
三年后,爬虫系统变成了一个分布式集群,20多台服务器协同工作,覆盖200多个信源,日均采集2000-3000条政策。系统经历了三次大的重构。
今天复盘这三次重构:为什么做、怎么做的、踩了什么坑。
三次重构
第一次重构:从"单机脚本"到"调度系统"(日采集量:几百条→2000条)
背景: 信源从十几个增加到50多个,单机爬虫开始撑不住了。任务堆积、互相干扰、经常超时。每天总有十几个信源的数据没采集到,需要手动补采。
重构方案:
-
引入任务调度器(XXL-JOB),统一管理所有采集任务
-
每个信源独立配置采集频率和超时时间
-
失败任务自动重试(最多3次)
-
采集结果统一写入消息队列,解耦采集和解析
效果: 采集覆盖率从70%提升到95%以上。调度器自动重试机制解决了大部分失败问题。
第二次重构:从"单机"到"分布式爬虫集群"(日采集量:2000条→5000条)
背景: 信源继续增加,超过100个。单机IP被部分网站限制频率,采集速度变慢。有些网站开始反爬,需要代理IP和浏览器模拟。
重构方案:
-
引入分布式爬虫框架(Scrapy Cluster),多台服务器协同工作
-
建立代理IP池(约50个节点),自动轮换IP
-
核心信源使用Puppeteer渲染,普通信源使用HTTP请求
-
采集和解析分离:采集节点只负责抓取,解析节点负责信息抽取
效果: 采集量翻倍,IP被封的问题基本解决。但系统复杂度大幅提升,运维成本增加了。
第三次重构:从"定时采集"到"增量检测+实时推送"(日采集量:稳定2000-3000条)
背景: 信源稳定在200多个,但政策更新频率不一。有的信源一天更新几十次,有的几天才更新一次。定时全量采集效率太低,浪费资源。
重构方案:
-
信源分级:一级信源5分钟扫一次,三级信源30分钟扫一次
-
增量检测:只采集"有变化"的内容,不做全量
-
变更推送:检测到更新后,自动触发采集→解析→入库→推送全链路
-
健康巡检:定时检查信源状态,异常自动告警
效果: 采集效率提升,资源利用率优化。系统从"全量采集"升级为"增量感知"模式。
三个关键决策
决策一:采集与解析分离
采集和解析耦合在一起,意味着采集节点既要处理网络请求,又要解析HTML、抽取结构化数据。如果某个网站的解析逻辑出了问题(例如页面结构变了导致抽取失败),采集也会失败。即使这个网站本身是可以正常访问的,解析错误仍然会让整条链路中断。
拆开之后,采集节点只负责"把页面拿回来",解析节点负责"从页面里提取信息"。解析失败时采集不受影响,可以各自独立处理异常,职责清晰,运维更灵活。
决策二:信源分级
对所有信源使用相同的采集频率是不合理的------国家级网站一天更新几十条,区县级网站可能一周才更新一条。如果都用5分钟扫一次,低更新频率的信源会带来大量无效请求,既浪费资源,也可能触发不必要的反爬限制。
将信源分为三级,一级信源(国家级、省级核心)短间隔巡检,三级信源(区县级、行业协会)长间隔巡检。把资源集中在最重要的信源上,提升整体采集效率。
决策三:数据质量优先于采集量
早期追求"采集量",觉得"越多越好"。后来发现有些政策采集回来数据不完整------正文缺失、附件链接无效、字段格式错误。用户看到的内容有问题,采集再多也没用。
后来在系统中加入"数据质量检查"环节:采集后自动检查字段完整性和附件有效性,发现问题的政策自动进入补充采集队列。数据质量优先于采集量。
结尾
爬虫系统从单机到分布式,经历了三次大的重构。每一次重构都解决了当时的主要问题,也引入了新的复杂度。
核心原则:先让系统"跑起来",再让系统"跑得稳",最后让系统"跑得聪明"。三个阶段缺一不可。