构建一个高性能的网页抓取器,互联网营销

   互联网的发展,使人类提前进入了信息爆炸的年代,在浩瀚无边的信息海洋里,如何快速、准确找到对自己有用的信息,就成了一个很有价值的研究课题,于是,搜索引擎应运而生。现在,国内外大大小小的搜索引擎有很多,搜搜也是这搜索引擎大军中的一员悍将。笔者有幸参与了搜搜研发过程中的一些工作,在这里写一些自己的理解与看法,权当是抛砖引玉,希望能够得到业内前辈们的一些指点。

  对于网页搜索引擎来说,它的基本处理流程,通常可以分为三个步骤:一是对海量互联网网页的抓取,也称下载;二是对已下载的网页进行预处理,包括抽取正文、建立正向索引、建立逆向索引等;三是向用户提供检索服务,包括对最终的检索结果进行打分排序,展示给用户等。从上面的介绍中可以看出,网页数据是网页搜索引擎最为根本的内容,没有丰富的网页数据做支撑的网页搜索引擎,它所能提供的服务是非常局限的。因此,一个强大的网页抓取系统(也称爬虫系统,又称Spider系统),对网页搜索引擎来说,是至关重要的。

      一个强大的Spider系统,不仅要能够及时发现每天互联网上新产生的网页,还要能够及时地更新已经抓取的网页,使之最大程度上与互联网上真实存在的页面一致。下图是一个完整的Spider系统的基本结构:

      从上图可以看出,一个完整的Spider系统,包括调度器(Scheduler)、抓取器(Crawler)、抽取器(Extractor)、Url库(Url DB)。调度器负责从Url库中选择需要抓取的Url列表,它是整个Spider系统的大脑;抓取器收到调度器所发送的待抓取Url列表,对其进行实际的抓取;抽取器收到抓取器下载完成的页面,对其进行处理,抽取页面正文,提取页面里包含的子链接;Url库接收并存储新发现的子链接相关信息,并对已抓取的Url的相关信息进行更新。这就是一个完整的Spider系统的基本的处理主流程。从本文的题目可以看出,本文要讲的重点是抓取器(Crawler),并不是整个Spider系统。下面就结合笔者之前所做的一些工作来谈谈,如何构建一个高性能的抓取器。

      通过上面的介绍,我们知道,抓取器的主要工作就是从互联网上抓取网页,看上去好像很简单,其实任何简单的事情,要做的特别的好,都不是那么的简单。首先,我们来看一下一个抓取器的整体的一个结构视图,如下图所示:

      从上图可以看出,一个抓取器总体上可以分为两层:一层是网络层(Network Frame),主要负责与上下游模块的通信交互,以及与Web服务器的交互进,行下载网页;一层是应用层(App Logic),完成抓取器内部的应用逻辑,比如Url对应的域名的IP的获取,压力控制(保证同一时间段内,对同IP的主机不会造成太大的压力),跳转识别(包括Http的跳转和页面内的跳转),页面附件(Js, Css, Frame等)解析及获取等一系列应用逻辑。因为抓取的网页内容经过一定的处理后,最终是要展示给用户的,而用户是通过浏览器来浏览页面的,所以我们希望抓取器所获取的页面与用户用浏览器打开的是一致的,因此,抓取器需要模拟一些浏览器的行为,做一些相关的工作,比如跳转识别等。下面分别从网络层和应用层两个方面来介绍一下具体的一些内容。

      抓取器的网络层,具体来说有两个方面的工作要做,一个方面是与上下游模块的通信交互,一个方面是与互联网上的Web服务器进行交互,获取待抓取Url列表中Url所对应的页面。一方面要及时响应上游的抓取请求,另一方面要到互联网上不停地下载待抓取Url列表中Url所对应的页面,同时还要把抓取完成的页面经过程一定的处理后发给下游,这就需要我们有一个高性能、大吞吐量、高并发量的网络层做为支撑。在这里笔者将介绍一个比较常用的异步网络通讯框架的设计,供感兴趣的朋友做参考。下图所示是该框架的一个线程模型:

      在上图中,IOMonitor是一个独立的线程,它的主要任务是检测网络IO事件,WorkThread是具体的工作线程。IOMonitor检测到网络IO事件后,向WorkThread发送消息进行通知。WorkThread在自己的线程中,不断地处理的收到的消息,实际的网络IO是发生在它里面的。WorkThread可以有多个,具体个数可以根据实际的应用需求进行设置。通常做法是与机器的逻辑CPU个数一样,这样会更加充分的利用机器的CPU资源。

      在Linux下,IOMonitor可以用Epoll来实现,通过调用epoll_wait()函数来获取有事件发生的socket及其上下文信息(context),然后把该socket上的事件,通知到处理其IO的WorkThread中去。关于这里Epoll的使用,再多讲一点,在这里推荐使用Epoll的ET(Edge Triggered)模式,如果要用LT(Level Triggered)模式,建议使用OneShot方式的LT。至于ET和LT各是什么,这里不赘言,感兴趣的朋友可以参考Linux下的Mannual。

      这里需要说明的是,这样做的目的是想更高效的地利用CPU资源。如果是在非Linux的平台下,应该也有类似Epoll的机制,原理大同小异,这里也不再赘言。另外,关于socket本身,还有两点需要说明一下:一是在这里最好用非阻塞的socket,这样在每一个环节都不会产生阻塞现象,不会产生因为前面的socket的阻塞而影响后面socket上事件的处理的情况;二是socket本身是有状态的,要在每个socket的上下文信息(context)中要维护该socket的当前状态,当WorkThread处理到某个socket上的事件时,要根据其状态采取不同的处理措施,可以采用类似下面的机制:

      应用层的主要任务是有效地组织整个抓取过程、完成相关的应用逻辑,具体包括DNS获取,IP压力控制,跳转识别,附件提取等一系统功能。事实上不同的抓取器的应用层所要做的工作会因整个爬虫架构的不同而千差万别。但这里重点不在于此,而是在于介绍一种事件触发(或者说消息通知)的模型,正是这种模型的运用,才使得我们的抓取器能够达到每秒几百甚至上千篇页面的抓取速度。

      实际上,上一部分中讲到的网络层的模型,也是一种简单事件触发的模型,只不过上面提到的事件,只有网络的可读(Read)、可写(Write)和异常(Exception)三种。事件触发模型的关键,首先是要把内部的任务抽象成一个有状态的Task(比如我们可以把抓取任务抽象为CrawlTask),然后对于每一个Task,它的整个处理流程是一个完整的状态机(State Machine),而且它的每次状态转移,都是由某个事件(Event)来触发的。这里的事件(Event)也是一种抽象,它可以是来自外部的网络事件,也可以是内部的某种事件,它的特点就是当事件处理器处理到它的时候,必然会伴随着某个Task的状态机的状态转移,换言之,Task的状态机是由事件(Event)来驱动的。通常的事件触发模型的设计中,会有一个或者多个事件处理器,当有事件发生的时候,其中某个事件处理器就会处理它,首先根据该事件找到它所对应的Task,然后调用该Task在当前状态下对应于该类型事件的处理函数,最后根据上面的处理结果,对该Task进行状态转移。

      以上即是本文的主要内容,最后想谈一点对今后的一些想法。记得09年及之前的几年,互联网上有一个叫SaaS的概念很火。SaaS的全称是“软件即服务(Software as a Service)”,大致的意思是说要把软件都做成服务,开发者不再向消费者直接卖软件,而是把软件做成一种服务,就像日常生活中的水、电一样,提供给用户。未来的抓取器,也不再仅仅是一个抓取器,它也可以发展成为一种抓取服务(Crawl Service),它不仅能够做为搜索引擎的Spider系统中用来抓取网页的一个单元来完成网页抓取的任务,还要能够满足其他用户的各种各样的抓取(下载)需求,因此,我们有理由相信未来的抓取器的发展也将是CaaS------Crawl as a Service。

时间: 2024-09-20 17:47:50

构建一个高性能的网页抓取器,互联网营销的相关文章

维基搜索收购网页的抓取器

中介交易 SEO诊断 淘宝客 云主机 技术大厅 据国外媒体报道,维基百科创始人吉米·威尔斯今年有一个宏大的计划,就是开发开源.开放的搜索引擎维基搜索,这一项目被誉为今年国际互联网的两个黑马产品之一 .周五,威尔斯透露了这一项目的一些进展. 据称,他已经收购了一家拥有抓取技术的公司,另外,维基搜索将依靠成千上万的用户电脑来分布式地抓取网页,而不是构建自己的"蜘蛛"服务器群. 威尔斯表示,他正在把若干个技术模块组建成完整的维基搜索,预计到今年年底,维基搜索将会提供一个公开测试版,这一依靠人

html-怎么用Jquery实现从一个网页抓取指定内容

问题描述 怎么用Jquery实现从一个网页抓取指定内容 已知一个网页的网址,现在抓取该网页的指定内容,比如说标题,发布时间,浏览次数等.怎么做????? 解决方案 http://www.gbtags.com/technology/javautilities/20120720jsoupjquerysnatchpage/ 解决方案二: 看看jquery 里面的load 方法. 其实做好还是用服务端语言做. 解决方案三: 客户端搞不了,有跨域问题,这种一般用采集软件来做,如火车头 解决方案四: 用Ht

几种PHP实现网页抓取的程序代码

抓取某一个网页中的内容,需要对DOM树进行解析,找到指定节点后,再抓取我们需要的内容,过程有点繁琐.LZ总结了几种常用的.易于实现的网页抓取方式,如果熟悉JQuery选择器,这几种框架会相当简单. 一.Ganon 项目地址: http://code.google.com/p/ganon/ 文档: http://code.google.com/p/ganon/w/list 测试:抓取我的网站首页所有class属性值是focus的div元素,并且输出class值 <?php include 'gan

用TinySpider进行网页抓取实例

本例中用到的maven坐标变化如下: ? 1 2 3 4 5 <dependency> <groupId>org.tinygroup</groupId> <artifactId>org.tinygroup.spider</artifactId> <version>0.1.0-SNAPSHOT</version> </dependency> 在百度中搜索笑话,看到这么一个网站:http://www.jokeji.

网页抓取工具之数据预处理

提取的数据还不能直接拿来用?文件还没有被下载?格式等都还不符合要求?别着急,网页抓取工具火车采集器自有应对方案--数据处理. 图片1.png 网页抓取工具的数据处理功能包括三个部分,分别是内容处理.文件下载.内容过滤.下面依次给大家介绍: 1.内容处理:对从内容页面提取的数据进行替换.标签过滤.分词等进一步处理,我们可以同时添加多个操作,但这里需要注意的是,有多个操作时是按照从上到下的顺序来执行,也就是说,上个步骤的结果会作为下个步骤的参数. 下面来逐个介绍一下: ①提取内容为空:如果通过前面的

善用网页抓取工具,数据轻松收入囊中

数据已走进各行各业并得到了广泛应用,伴随着应用而来的则是对数据的获取和准确挖掘.我们可应用的数据多来自内部资源库以及外部载体,内部数据整合即用,而外部数据却需要先行获取.外部数据的最大载体就是互联网,网页中每天难以数计的增量数据里,就包含着许多对我们有利用价值的信息. 如何最高效地从海量信息里获取数据呢?网页抓取工具火车采集器有高招,以自动化的智能工具代替人工的数据收集,当然更高效也更准确. 一.数据抓取的通用性 作为通用的网页抓取工具,火车采集器基于源代码的操作原理让可抓取的网页类型达到99%

c#-C# 网页抓取保存为图片

问题描述 C# 网页抓取保存为图片 给个网址,然后把整个网页以图片的形式保存到本地要求 :1. 要保存的是整个网页,从头到尾2.如果网页超出屏幕,请模拟下拉滚动条至网页底部,待网页所有元素加载完毕后,再保存 解决方案 这个需求对于那些所谓"瀑布流"方式加载的网页,典型的,新浪微博和google图片搜索结果,它下拉下来是无限长的,而你的内存不是无限大的,一下子就把你的程序搞死了. 解决方案二: c#获取整个网页截图 解决方案三: 现在的问题是如何判断一个网站完全打开,包括所有的图片已经打

初学指南| 用Python进行网页抓取

引言 从网页中提取信息的需求日益剧增,其重要性也越来越明显.每隔几周,我自己就想要到网页上提取一些信息.比如上周我们考虑建立一个有关各种数据科学在线课程的欢迎程度和意见的索引.我们不仅需要找出新的课程,还要抓取对课程的评论,对它们进行总结后建立一些衡量指标.这是一个问题或产品,其功效更多地取决于网页抓取和信息提取(数据集)的技术,而非以往我们使用的数据汇总技术. 网页信息提取的方式 从网页中提取信息有一些方法.使用API可能被认为是从网站提取信息的最佳方法.几乎所有的大型网站,像Twitter.

《用Python写网络爬虫》——2.2 三种网页抓取方法

2.2 三种网页抓取方法 现在我们已经了解了该网页的结构,下面将要介绍三种抓取其中数据的方法.首先是正则表达式,然后是流行的BeautifulSoup模块,最后是强大的lxml模块. 2.2.1 正则表达式 如果你对正则表达式还不熟悉,或是需要一些提示时,可以查阅https://docs.python.org/2/howto/regex.html 获得完整介绍. 当我们使用正则表达式抓取面积数据时,首先需要尝试匹配 元素中的内容,如下所示. >>> import re >>&