当前位置: 首页 > 科技观察

高级架构师实战:如何以最小的成本完成爬虫的需求

时间:2023-03-19 15:08:22 科技观察

1.出身在我工作的很多公司中,有很多领域,比如房地产、电子商务、广告等领域。虽然业务千差万别,但都涉及到爬虫领域。在开发了更多的爬虫项目之后,我们自然会面临一个问题——这些开发的爬虫项目是通用的吗?是否有可能以相对较低的成本完成一个新的爬虫需求?在运维过程中,工具能否基于配置构建分布式爬虫应用?这就是我们今天要讨论的话题。2.项目需求在项目之初,我们尝试从使用的角度提出了几点需求。1、分布式爬虫由于爬虫的量可能非常大,一台机器不足以处理百万级以上的爬虫任务,所以分布式爬虫应用是首先要面对和解决的问题。2、模块化、轻量级我们将爬虫应用分为“应用层、服务层、业务处理层、调度层”四个角色。3、可管理可监控管理监控是一个系统,即配置可管理,运行可实时监控。当系统正常运行时,可以更改爬虫的配置。一旦实时监控爬虫出现异常,可以实时修正配置进行干预。一切都可以通过UI界面进行操作。4.通用性和可扩展性。爬虫业务往往是多变的,不同领域的爬虫需求也不尽相同。例如房源抓拍,包括图像抓拍、社区信息抓拍、房源去重等模块。新闻抓取包括内容抓取、文本抽取、信息摘要等,因此系统需要能够支持业务扩展需求,能够支持不同业务使用同一个框架进行应用开发。三模块分解针对业务需求,我们将系统分解为多个应用模块。1.应用层应用层面向管理员和系统维护人员。主要分为两个模块,系统配置模块和运行管理模块。系统配置模块:系统配置模块包括爬虫网站管理配置、在线测试等功能。运营管理模块:运营管理模块包括实时抓包量统计、分析、准确率等,甚至包括故障原因和故障量。系统操作人员可以从操作模块得到实时反馈,使用系统配置模块进行配置修正,在线测试无误后使配置生效,并实时监控新配置的效果。2.服务层服务层是整个系统传输的中心,相当于整个分布式和集中式的系统总线和数据总线。服务层提供http/thrift接口读取数据库,输出配置信息。提供网站爬虫配置接口。实时从数据库中读取配置信息,响应业务层的配置请求。提供业务层的输出写入接口。实时接受业务层爬取的信息汇总,包括正确数据量、错误数据量、错误原因。提供实时报表统计分析。响应应用层运营管理模块,查询数据库,实时提供数据分析报告。3、业务处理层业务处理层是整个爬虫系统的核心,可以分为多个应用服务器进行处理。业务处理层主要包括解决两件事。如何获取url获取到url后,如何处理(1)如何获取url对于爬虫来说,如何获取url非常重要。我们将这个过程定义为发现系统。对于发现系统,目标是如何发现要爬取的网站的详细url列表,发现尽可能完整。a假设场景A我们访问一个电商网站:打开首页-打开分类页-可能有多层分类页-逐层点击-直到最小的分类页。当你打开这个分类页面时,你会发现分类页面下的所有分页页面,你可以通过一次向下滚动一页来获取分类页面上的所有产品。b假设场景B我们访问一个汽车网站:打开首页-找到品牌页面-然后找到汽车系列-最后找到车型页面。通过上面的场景分析,我们可以得出一个结论,人们可以非常智能的找到所有需要抓取的详细页面,即电商产品和车型页面。那么,是否可以通过配置来模拟这个过程呢?请看下图:备注如下:*root_info:定义发现模块的入口页面,就像人打开公交车站的网页一样,后续的发现都是从这些入口页面开始的。这里举的例子是某汽车网站的品牌列表页面,按照“模板”应用变量的配置,共有100个入口页面。*steps:依次遍历100个入口页面,分别执行steps中定义的步骤。机器模拟人的方式来查看和浏览。在每一步中,都会使用“link_module”定义的类进行逻辑处理。读取入口页面的html,结合“sub_prefix”、“sub_suffix”、“select”定义的内容,得到页面子区域的html。使用“link_match_method”方法(带有前缀contains、match等)来提取子区域的链接。每个链接都匹配“link_pattern”,匹配成功的URL进入下一步。每一步得到的url在下一步自动处理,处理逻辑在a-c上面递归,直到"last_step"为真。这里,“last_step”中找到的url为true,也就是发现系统最终需要获取的url列表。发现系统通过配置,结合人的浏览习惯,经过多次迭代,最终得到网站的详细页面url列表。由于每个步骤的链接提取规则和步骤数据都是手动定义的,因此可以适应大多数网站的发现系统。当然,越复杂的网站配置可能越复杂,但都是一样的。2.获取到url后如何处理的前提当然是每个业务的处理不一样。有提取页面属性、文本提取、图片获取,甚至与现系统对接等功能。由于业务处理不一致,很自然地想到通过配置来定义责任链体系,就像著名框架Netty中的Pipeline设计一样。在处理的时候,定义一个Context上下文处理类,所有的中间结果都悬浮在这个Context中。描述的比较空洞,下面结合实际案例来看。备注如下:获取到一个url后,读取配置,当url匹配到“site”时,应用当前的“site”规则。*管道定义了责任链的处理流程,这里定义为“抓取模块、Javascript处理模块、通用解析模块”。对应的处理如下:先执行抓取模块,获取html。然后执行Javascript处理模块,输入为html,解析html。这里可能是评论或价格。简而言之就是对动态加载项进行处理,然后在“通用解析模块”*“parser_rules”中定义解析模块最终输出的是kv,在java中是map,在python中是dict。即从上一步的html中,找到每一个推荐的“滋滋”,执行“前缀”、“后缀”,即去除前缀和后缀(过滤如“价格:xxx元,前缀为“价格:”,后缀为yuan)。顺便说一句,sizzle也是一个开源技术,据说大名鼎鼎的Jquery也是一个“sizzle”引擎,在Java中可以使用Jsoup进行解析和加工。你怎么知道需要抓取“嘶嘶”的内容呢?具体可以和firebug插件结合起来,选中即可获取。选择好之后,结合应用层的管理工具,就可以进行测试了。*"isrequire"可以看到,配置项中有"isrequire",表示是否需要这个内容。如果在实际处理过程中需要而获取不到,那么在爬取过程中就会记录错误,错误原因自然是“$key为null”。另外,每个模块都可能出错,一旦出错,后面就没必要执行了。因此,在爬取过程中,业务处理层从服务层获取一批url(默认100个)后,处理完这100个url后会上报给服务层。报告内容为:当前任务处理机,何时处理100页。有多少不同网站成功,有多少失败,有多少模块失败,解析模块有多少字段失败。所有这些信息都在运行监控系统中实时统计并图形化绘制。必要时可发出告警,维护人员可实时介入。问:我有一个问题,如果我添加了另一个auto.com网站,我该怎么办?A:其实很简单,再加一个配置就可以了。业务定义流水线,如果有分析需求,填写相应的分析项即可。以上两个系统,发现系统和处理系统,在我们的实际生产中是通过以下几个步骤来运行的。发现系统是累积发现要爬取的网站的详细页面,因为它是一个累积的、连续的过程。因此,肯定会继续无限接近网站页面的100%。处理系统每次通过服务层获取配置信息(可由维护人员实时修正)和需要获取的列表进行处理。抓包列表根据业务的优先级分为普通队列和优先级队列,通过任务调度系统统一管理和配置。4.调度层调度层主要是业务系统。新增网站任务调度网站发现频率,包括增量发现频率和全发现频率网站爬取优先推送到队列断点持续爬取管理...4.系统架构设计从业务模块角度:应用层,服务层,业务处理层、调度层从功能系统角度:发现系统、抓包系统、配置系统、监控系统从可扩展性角度:自定义责任链、自定义属性抽取从实时性能角度:Real-时间抓包,实时配置生效,实时监控,实时测试从系统架构来看:分布式架构,服务层主从切换设计,轻量级(只依赖队列,数据库,java)5.传奇【本文为专栏组织《奇安科技》原创文章》,请微信联系原作者公众号(bigsec)]点此查看该作者更多好文