网络论坛爬虫设计

2024-07-31

网络论坛爬虫设计(共7篇)

网络论坛爬虫设计 篇1

0 引言

网络爬虫也称网络蜘蛛, 它为搜索引擎从万维网上下载网页, 并沿着网页的相关链接在Web中采集资源, 是一个功能很强的网页自动抓取程序, 也是搜索引擎的重要组成部分, 爬虫设计的好坏直接决定着整个搜索引擎的性能及扩展能力。

网络爬虫按照系统结构和实现技术, 大致可以分为:通用网络爬虫、主题网络爬虫、增量式网络爬虫、深层网络爬虫。实际应用中通常是将几种爬虫技术相结合。

1 通用爬虫的设计与实现

1.1 工作原理

通用网络爬虫根据预先设定的一个或若干初始种子URL开始, 以此获得初始网页上的URL列表, 在爬行过程中不断从URL队列中获一个个的URL, 进而访问并下载该页面。页面下载后页面解析器去掉页面上的HTML标记后得到页面内容, 将摘要、URL等信息保存到Web数据库中, 同时抽取当前页面上新的URL, 保存到URL队列, 直到满足系统停止条件。其原理如图1所示。

1.2 爬行策略

为提高工作效率, 通用网络爬虫会采取一定的爬行策略优先爬取重要的网页。常用的有深度优先和宽度优先策略。宽度优先算法的设计和实现相对简单, 可以覆盖尽可能多的网页, 是使用最广泛的一种爬行策略。

一个爬虫如何利用宽度优先遍历来抓取网页呢?在爬虫中, 每个链接对应一个HTML页面或者其它文件, 通常将HTML页面上的超链接称为“子节点”。整个宽度优先爬虫就是从一系列的种子节点开始, 把这些网页中的“子节点”提取出来, 放到队列中依次进行抓取。被访问过的节点放入到另一张表中, 过程如图2所示。

1.3 爬虫队列设计

爬虫队列设计是网络爬虫的关键。因为爬虫队列要存储大量的URL, 所以依靠本地链表或者队列肯定是不够的, 应当寻找一个性价比高的数据库来存放URL队列, Berkeley DB是目前一种比较流行的内存数据库。根据爬虫的特点, Hash表成为了一种比较好的选择。但是在使用Hash存储URL字符串的时候常用MD5算法来对URL进行压缩。

在实现了爬虫队列之后就要继续实现Visited表了。如何在大量的URL中辨别哪些是新的、哪些是被访问过的呢?通常使用的技术就是布隆过滤器 (Bloom Filter) 。利用布隆过滤器判断一个元素是否在集合中是目前比较高效实用的方法。

1.4 设计爬虫架构

爬虫框架结构如图3所示。

其中:①URL Frontier含有爬虫当前准备抓取的URL;②DNS解析模块用来解析域名 (根据给定的URL决定从哪个Web获取网页) ;③解析模块提取文本和网页的链接集合;④重复消除模块决定一个解析出来的链接是否已经在URL Fronier或者是否最近下载过。

下面通过实验来比较一下我们设计的爬虫抓取网页与原网页的对比, 见图4、图5。

通过比较可以发现, 由于原网页有动画等多媒体元素, 虽然爬虫无法抓取下来全部内容, 但基本上是一个完整的爬虫。

2 限定爬虫的设计与实现

限定爬虫就是对爬虫所爬取的主机的范围作一些限制。通常限定爬虫包含以下内容:①限定域名的爬虫;②限定爬取层数的爬虫;③限定IP的抓取;④限定语言的抓取。

限定域名的抓取, 是一种最简单的限定抓取, 只需要根据当前URL字符串的值来作出限定即可。

限定爬虫爬取的层次要比限定域名更复杂。限定IP是限定抓取中最难的一部分。通常分为限定特定IP和限定某一地区的IP。限定特定IP抓取较为容易, 只要通过URL就可以获得主机IP地址, 如果主机IP在被限制的列表中就不抓取。否则正常工作。

想要限定IP抓取, 首先要根据主机字符串获得IP地址。下面我们通过实验来得到IP地址:

贵州民族学院:

主机域名:www.gznc.edu.cn

IP地址:210.40.132.8

贵州大学:

主机域名:www.gzu.edu.cn

IP地址:210.40.0.58

根据URL得到IP地址之后, 就要根据IP地址对某一地区的IP作出限制。但是需要有一个IP与地区对应的数据库, 网上很多这样的数据库都是收费的, 在此我们使用的是腾讯公司推出的一款免费数据库“QQWry.dat”, 只要输入IP地址就可以查到对应IP地址所在的区域。

输入:210.40.0.58

输出:

贵州省贵阳市:贵州大学输入:210.40.132.8

输出:

贵州省贵阳市:贵州民族学院

根据IP地址制作一张列表, 将限制地区的IP地址写入列表, 爬虫如果检测到要抓取的IP地址属于该列表, 就放弃抓取, 这样一个限定爬虫就完成了。

3 结束语

本文介绍了爬虫的工作原理, 重点介绍了通用爬虫和限定爬虫的设计及实现, 并通过实验证明本文设计的爬虫可以达到预期效果。

参考文献

[1]孙立伟, 何国辉, 吴礼发.网络爬虫技术的研究[J].电脑知识与技术, 2010 (15) .

[2]于成龙, 于洪波.网络爬虫技术研究[J].东莞理工学院学报, 2011 (3) .

[3]罗刚.自己动手写搜索引擎[M].北京:电子工业出版社, 2009.

[4]唐波.网络爬虫的设计与实现[J].电脑知识与技术, 2009 (11) .

[5]龚勇.搜索引擎中网络爬虫的研究[D].武汉:武汉理工大学, 2010.

社区网络爬虫的设计与实现 篇2

随着互联网的不断发展, 以用户创造 (UCG) 内容为主的Web2.0逐渐代替了传统的网站。作为Web2.0的代表, Facebook, twitter每天要经过数十亿的用户, 产生TB级的数据。国内的人人网, 开心网每天也会流经近亿的用户。这类网站的数据都是由普通用户创造的, 不会经过专业的编辑, 大多与用户的日常生活相关。关于这类数据的探讨研究对分析人群特点, 获得统计规律具有很好价值和重要意义。

传统的网络爬虫以种子站点为起点, 通过页面之间的超链接[1], 利用广度优先的方式获取数据。由于互联网数据规模庞大, 不能及时抓取每一个网站的数据, 所以网站要经过很长的时间计算出更新规律, 按照优先级进行更新。而社区互联网的数据更新很快, 更新频率也在变化, 一般的社区互联网都需要登录后才能访问, 而且其数据大多都是动态加载, 因此传统的爬虫很难做到及时有效地获取这部分数据。

本文以国内最大的社区互联网—人人网的用户状态信息为例, 设计并实现了一种新型智能的网络爬虫, 可以解决登陆问题, 以人与人的关系代替以往的超链接, 并且动态计算数据更新频率, 使数据具有很高的准确性和时效性。

1 相关技术背景

1.1 模拟登陆

与传统的网站不同, SNS网站需要登录后才能进入个人主页, 未登录的访问将会被跳转到登陆页。而页面与页面之间的联系不再通过最常见的超链接, 而是借助用户之间的关系, 例如, A和B互为朋友, 则在访问A页面的时候可以从A的朋友列表中找到B, 并将B加入缓存队列中。

传统的爬虫没有登陆功能, 因此需要为SNS网站专门设计一种爬虫。该爬虫支持登陆, 并且可以分析用户的关系网, 从特定用户出发, 抓取大量用户的信息。

超文本传送协议 (HTTP) 是一种通信协议, 允许将超文本标记语言 (HTML) 文档从Web服务器传送到Web浏览器。HTML是一种用于创建文档的标记语言, 这些文档包含到相关信息的链接。可以单击一个链接来访问其它文档、图像或多媒体对象, 并获得关于链接项的附加信息。

HTTP是一个属于应用层的面向对象的协议, 由于其简捷、快速的方式, 适用于分布式超媒体信息系统。该协议于1990年提出, 经过几年的使用与发展, 得到不断的提升和完善。较早使用的是HTTP/1.0, 现在WWW中使用的是HTTP/1.1, 而HTTP-NG (Next Generation of HTTP) 的议案则已经提出, 正在运作中。

HTTP是无状态协议, 每一次访问都需要和Web服务器重新连接, 又因为其无记忆的特点, 对于网站来说很难记录上次访问的状态。这样用户在一个页面的操作就没法影响到其他页面, 所以, 需要一种机制来实现用户登录的判断。Session解决方案就是在这种背景下被提出来的。Session方案是在用户的每次会话中, 提供一种全局变量的实现方式, 使得这个全局变量在此次会话中访问任何页面都有效, 通过这种方式判断用户是否登录。

Session的实现方式有两种, 一个是通过Cookie, 另一个是通过URL重写。

(1) 通过Cookie。Cookie是保存在客户端的一小段信息, 服务器在响应请求时可以将一些数据以“键-值”对的形式通过响应信息保存在客户端。当浏览器再次访问相同的应用时, 会将已有的Cookie通过请求信息带到服务器端。

(2) 通过URL。通过cookie可以很好地实现session, 但是如果客户端由于某些原因 (比如出于安全考虑) 而禁用cookie, 在这种情况之下, 为了使session能够继续生效, 可以采用URL重写。URL重写很简单, 在cookie未被禁用的情况下, 与第一种情况没有什么区别;但在cookie禁用时, 则会将Session ID的信息作为请求地址的一部分传到了服务器端, 这就是URL重写的意义所在。

1.2 网页更新规律

学术界对网页变化规律的相关研究己经开展多年, 通过大量的研究工作发现泊松过程是与网页变化规律吻合得较为贴切的一个数学模型[2], Brien和orimes对大量的网页进行了详细的测试发现[3], 虽然存在部分页面变化不符合泊松过程, 比如一些完全定期自动更新的网页等, 但是统计发现变化规律不符合泊松过程的这些页面却只占很小部分[4] (小于百分之五) 。

泊松过程常用于对一系列独立、随机、有固定频率的随机事件的过程描述。假定P的变化规律是, 网页P下次变化所需时间是T, T的概率密度为:

网页P在 (0, t) 变化的概率为:

1.3 目标数据

状态 (status) 是社区网络中很常见的数据类型, 一般在250字以下, 来源于用户, 大多代表着用户某一时间的心情或者对某事的看法、评论, 这类数据通常具有以下几个特点:

(1) 碎片化。数据通常比较短小。

(2) 时间标签。每一条数据的后面都会附带时间。

(3) 真实性。由于数据基本都来自于用户本身, 相对于专业网站来说, 其真实性更高, 更能代表普遍规律。

(4) 互动性。数据一般会带有其他用户的评论。

(5) 历史记录。数据在不被删除的情况下都可以保存。

2 系统架构

系统分为结点获取模块、结点筛选模块、数据抓取模块、数据储存模块, 系统架构如图1所示。

由图1可见, 各功能模块的作用分析如下:

(1) 结点获取模块。首先, 将种子用户放入缓存队列中, 处理过程为:从缓存队列中取一个结点, 获取该结点的所有数据;其次, 通过分析用户之间的好友关系, 再将这些新结点存入缓存队列中, 依次进行。

(2) 结点筛选模块。通过分析结点获取模块中获得的结点, 优先选取更新概率比较大的结点加以更新。

(3) 数据抓取模块。模拟浏览器行为, 获取有用的html页面, 过滤后提取相关数据内容。

(4) 数据储存模块。为抓取的数据节点以及数据内容建立数据结构, 以数据表的形式存储在数据库中, 便于下一步的应用。

3 系统设计与实现

3.1 模拟浏览器登录

文中实现了登陆爬虫的两种实现方式:

(1) 在登陆页面, 模拟提交表单。

(2) 直接导入已登录的cookie。

对这两种方式展开分析如下:

(1) 模拟提交表单。需要提供用户名、密码, 限制性比较大, 但是可靠性高, 而且没有时间限制, 其运作流程如下:

(1) 访问主页, 获取Httpt头部的Set-cookie值;

(2) 设置cookie值, post用户名和密码至登陆页面;

(3) 保存返回的set-cookie值, 以供方式 (2) 使用;

(4) 设置新的cookie值, 再次访问主页, 并处理Location跳转。

(2) Cookie不需要用户名密码, 可以很方便、安全地导入, 又不暴露用户的隐私, 利于系统的分布式实现, 可以支持导入第三方的账户, 但是由于本地cookie的限制, 一般只有3~5天的使用期限。

3.2 结点获取模块

首先, 给出结点数据结构的定义如下:

为了增加系统的可扩展性, 结点获取模块采用C/S结构, 客户端从服务端获取需要采集的结点, 并将新的候选结点传送至服务端, 服务端储存已采集的结点信息, 并建立候选采集点缓存队列, 向客户端分发需要采集的结点, 同时保证每个客户端采集的结点不重复。主要流程如图2和图3所示。

3.3 结点筛选模块

将获取的结点数据按照以下方式处理:

参数=更新总状态数/ (最后更新时间-初发状态时间)

更新概率=参数觹 (当前时间-最后状态时间)

按照更新概率的降序排列, 取前N个数据, 生成数据抓取队列, 每抓取一个结点时, 重新计算该结点的更新频率, 公式为:

更新频率= (抓取的新状态数量+状态/总数) / (当前时间-初发状态时间)

式中:状态数量=抓取的新状态数量+之前的状态数量, 同时一并更新最后状态时间, 以及存储最后更新时间。

3.4 数据抓取模块

在此, 给出目标数据结构的定义如下:

数据抓取模块通过状态页面的ajax调用, 获得数据页面, 利用xpath的方式获取相关数据。以下是截至发稿日时, 本文发现的人人网的数据获取接口。

(1) 获得非好友的状态 (id为所查看用户的id, curpage代表分页) 。

http://status.renren.com/status?id=229457146&__view=async-html&curpage=1

(2) 获得非好友的状态评论 (owner为所查看用户的id, doingid与source均为状态id, t代表类型, request Token、rtk为登陆时系统发送的token值) 。

http://status.renren.com/feedcommentretrieve.do?doing Id=2-571071868&source=2571071868&owner=229457146&t=3&request Token=140378053&_rtk=d41efe1f

3.5 数据储存模块

为方便数据的管理和分析, 本系统采用mysql数据库存储数据, 并为结点信息和数据信息建立了两张表, 即node、status表。

4 实验

在结点筛选模块中, 对N分别取值500, 5 000, 50 000, 得到结点的更新情况如图4所示。

可以看到, 80%以上的结点都发生了变化, 所以系统可以很及时地获取用户更新的数据。

由此, 按一台机器一秒钟可以访问三个页面, 可以推知:

在新增结点中, 平均每个结点包含9页, 每个页面包含20条状态, 每台机器每天可以新增加2w个新结点, 360w条数据。

在更新结点中, 平均每天可以更新100w条新数据。实验结果表明, 系统具有很好的性能。

5 结束语

本文设计并实现了社区网络爬虫, 该爬虫可以解决传统爬虫遇到的登陆和数据更新问题, 并且支持分布式的扩展。试验结果表明, 该爬虫具有良好的性能, 可以投入到日常的使用中。

摘要:社区互联网是以用户创造内容为主的新型互联网, 具有很高的统计价值, 由于权限和数据更新频繁等限制, 传统的网络爬虫很难获取这一部分数据, 设计并实现了一种可以自动登录并可以根据更新频率快慢智能抓取数据的爬虫, 不同于以往爬虫以页面为粒度, 该爬虫以人为最小粒度, 并以人与人之间的关系为抓取依据, 在获取这类数据上有很好的性能。

关键词:社区互联网,智能爬虫,数据挖掘

参考文献

[1]CAI R, YANG J M, LAI W, et al.iRobot:an intelligent cra-wler for Web forums[C]//Proc of the 17th World Wide WebConf.Bejing, 2008:447-456.

[2]BREWINGTON B, CYBENKO G.How dynamic is the web芽[J].Computer Networks, 2000:257-276.

[3]FETTERLY D, MANASSE M, NAJOR, et al.A large-scale s-tudy of the evolution of Web pages[C]//Proc of the 12th Int'sWorld Wide Web Conf.New York:ACM Press, 2003:669-678.

网络论坛爬虫设计 篇3

Web2.0是相对Web1.0的新一代互联网应用的统一名称。Web1.0的重要特征是用户通过使用浏览器获取静态的网络信息。Web2.0则侧重于用户与用户之间的交流和沟通, 用户不仅作为网页内容的查看者, 同时也是网页内容的创造者。所说的网页内容的创造者是指互联网上的所有用户不再只是互联网内容的读者, 同时也成为了互联网内容的作者;不再仅是冲浪于互联网海洋之中, 同时也是海洋波浪的制造者;在模式上由纯粹的“只读”变为“读写”进而发展成为“共同建设”;由简单被动地接收互联网信息转变为主动创造互联网信息, 从而增加了互动, 更加符合用户的使用习惯。

近年来, 随着Web2.0的兴起, 在Web开发中运用AJAX技术的网站越来越多, 这些技术的应用带来了更好的用户体验、很多新概念和Web UI设计, 同时, 由于AJAX技术可以动态改变页面内容, 改造了传统Web页面的结构, 导致单纯抓取静态Web页面的网络爬虫抓取的内容少于页面呈现的内容, 这些动态内容给网络爬虫的设计带来极大挑战, 使得爬虫不能获取到网页页面所呈现的全部文本。

本文研究能够支持AJAX的网络爬虫的原理, 实现一个支持AJAX且能够进行定制任务的网络爬虫, 高效率地对网页信息进行采集。第1节介绍国内外对AJAX页面的抓取研究情况, 第2节介绍支持AJAX的爬虫的设计及具体实现, 第3节通过实验验证了支持AJAX的爬虫的可行性。

1 相关工作

现阶段, 主流的搜索引擎, 例如:Yahoo!和Google等, 都无法对AJAX动态网页建立索引, 也就是说不能利用现有的搜索引擎来查询动态网页的内容。而能够支持AJAX的搜索引擎还处于研究阶段, 罗兵使用基于协议的动态页面抓取方法, 获取AJAX网页内包含的Java Script代码片段, 通过设计脚本语言解释器直接分析脚本代码, 仿照浏览器功能顺序执行脚本文件, 用来模拟页面的状态转换[1], 肖卓磊在之后的研究中也采用了类似的处理方法[2];曾伟辉、李淼利用切片算法构造了程序层次模型, 解决了有序执行Java Script脚本的问题[3];Frey[4]和Matter[5]改进了开源的Java Script解释器Rhino[6], 用来实现状态转换和脚本执行。实现全部功能的脚本解释器较为困难, 即便是已开发多年的Rhino项目, 依旧有很多的脚本代码不能正常执行, 于是, 更多的研究人员将研究重点落定于嵌入式浏览器组件, 运用组件来模拟AJAX页面的渲染并实现脚本的执行, 以达到自动转换状态的目的;在国内, 采用类似方法研究的是王映[7]和金晓鸥[8], 研究对使用网络爬虫分析脚本语言的技术进行了一些研究, 前者使用的是开源的Java Script引擎Spider Monkey, 而后者利用的是Rhino。因其均解析了包含Java Script脚本代码的动态页面, 从页面中抓取了Java Script代码, 由此获得了网页上的URL, 并实现了内容爬取。Frey和Matter扩展了Cobra工具集[9], 完成了动态解析和加载HTML代码, 然后在内部形成DOM结构树, 并通过DOM树获取状态包含的内容。类似于状态转换问题, 为了最大限度地利用现有的技术, 多数的状态内容获得方式是采用嵌入浏览器组件作为运行AJAX容器, 并使用浏览器的外部接口实现和DOM树的数据交互, 由此而获得完整的内容[10,11,12,13]。

在控制转换方面, 较为常用的方式是采用事件过滤机制, 对已经过滤后的事件逐一进行触发。为了提高执行效率, Xia[12]和Duda[14]均提出让用户能够自定义过滤规则, 也就是加入拒绝规则和接收规则, 如此即使得只有在符合规则的集合里才能进行状态转换;Mesbah等采用面向领域的手工配置、HTML元素注解和全自动扫描三种方式来对状态转换进行控制[10];Matter则提出了一种启发式的爬行策略, 尽量避免从不同路径进入相同的页面状态[5]。

2 AJAXCrawler爬虫设计方案及实现

由于Web 2.0的流行, 使用AJAX技术的网站越来越多, 本文采用了Rhino引擎对AJAX进行了支持。

2.1 Java Script引擎Rhino

Rhino采用Java语言实现的Java Script脚本引擎。Rhino用在Java程序中, 为最终用户提供脚本化能力。Rhino包含Java Script编译器、Java Script解析器、Java Script调试等模块。下面即对脚本编译模块和脚本解释模块进行全面分析。

2.1.1 脚本编译模块

编译器的输入是Java Script代码, 输出是Java Script数据对象。Java Script结构中包含了字节码、注释、string池、数据以及标识符。Java Script中还包含Objects, 函数等。其中, 函数也是一段嵌套的Java Script代码。编译器由以下三部分组成:随机逻辑 (randomlogic) 的词法扫描器, 用来创建AST的递归下降分析器, tree‐walking代码生成器。编译过程是由函数Main.process Source () 来完成的, 将输入的字符串或者Java Script代码转化成流文件进行编译。在编译过程中, 所有的变量, 符号以及命令等都由词法分析器进行解析, 再利用内部特定的符号标识, 放入对应的数据栈中, 最后将得到的数据用树形结构返回, 便于Rhino引擎编译。在少分号或者是可赋值表达式等情况下, 用语义和词法的反馈 (feedback) 机制来消除歧义。编译器没有错误校正, 因此, 只要遇到错误, 就立即停止。另外, 编译器还在编译完成的script结构中加入sourcenotes信息, 以便用户调用to Source () 函数进行反编译时使用。

2.1.2 脚本解释模块

类似大多数的Java Script引擎, Rhino的interpreter是一个单线程的大型循环函数, 该函数每次解释bytecode的一个指令。在这个大型函数中, 采用的是switch语句, 即根据所要执行的bytecode的不同, 跳转到不同的执行代码段中。大多数情况下, 如果一段Java Script代码调用另一段Java Script代码, 则引擎只会使用Java Script的栈空间, interpreter也是顺序执行的。但如果Java Script代码调用了java代码, 再由java代码调用Java Script代码, 就会引起interpreter的重入问题。需要一提的是, 这个大型函数是可重入的。对于interpreter所需要的各种状态都是通过参数的形式在interpreter函数进入时完成传递的。绝大多数的状态都保存在数据结构Context中。因此, 在Rhino里, 所有的公共API接口以及大部分的函数接口中, 第一位参数均是一个Context的指针。

2.2 AJAX爬虫架构设计

爬虫系统分为两部分, 第一部分是预处理阶段, 这个阶段实现URL净化, 并去除不必要抓取的URL, 类似于过滤器的功能。第二部分是网页真正抓取的部分, 由于网页下载比较耗时, 为了充分利用资源, 此处采用了多线程。抓取阶段获得网页, 析出网页内部的链接, 而后进行预处理。并不是每个网页内部的链接都是需要抓取的, 网页内部的链接可能包含以前抓取过的重复URL, Robots协议禁止抓取的URl等。Clean URLs是经过净化后的URL库, 里面存放的都是需要抓取的URL。爬虫的架构如图1所示。

2.3 AJAX引擎设计

AJAX引擎提供对网页中AJAX的支持, 能够对网页中的js代码进行解析、执行, 由此得到网页动态内容。AJAX引擎架构如图2所示。

由图2中可见, AJAX引擎主要有三个组成部分。对AJAX页面的解析按照下面的顺序进行。

(1) Crawler通过HTTP请求, 获取需要抓取的页面。此时的页面是一个含有AJAX代码的页面, 其中没有真正的内容;

(2) DOMBuilder对页面进行分析, 建立DOM树, 提取出其中的JS代码, 触发相应的事件;

(3) 将AJAX代码送入Java Script引擎执行, 在执行的过程中, 同时根据JS对象与HTML对象映射修改HTML对象;

(4) 将执行结果重新组合生成新的页面内容, 返回给Crawler。

3 实验数据结果

实验基于Java平台, 开发环境采用Eclipse, Java虚拟机版本为JDK1.6.0, Rhino版本为1.7R2, 实现AJAXCrawler。本文主要对AJAXCrawler进行了吞吐量的测试, 并与普通的爬虫进行下载速度的对比。

3.1 吞吐量实验

吞吐量实验是测试AJAXCrawler数量以及每个AJAX-Crawler启动线程数与下载速度的关系。若启动的AJAX-Crawler或者每个AJAXCrawler中的线程数太少, 则系统不能完全利用计算机的资源, 反之则会因为带宽、数据竞争等而降低效率。测试机器为一台普通PC机, 硬件配置以及软件配置如表1所示。

AJAXCrawler测试任务为天涯博客, 通过改变AJAXCrawler以及每个AJAXCrawler内线程的数目, 测得的数据如表2所示, 绘制成折线图, 如图3所示 (单位:页面数/10分钟) 。

由表2和图3可以看出, 在当前的计算环境和网络环境下, 当选取任务数为3, 每个任务内有3个线程的时候, 系统运行效率达到较优, 平均每10分钟能够下载网页1 679页。

3.2 AJAXCrawler与普通爬虫比较实验

此实验以网易的评论为测试对象, 分析AJAXCrawler的效率。由于普通爬虫无法抓取到动态内容, 此处的量化指标不再以页面数/10分钟作为单位, 而是选择Kb/second作为单位。测试结果如表3所示, 绘制成折线图如图4所示。

由表3和图4可以看到, AJAXCrawler无论是几个任务并发执行, 都相应地比普通的Web Crawler下载速度慢。除去实验环境偶然因素外, 最主要的影响因素应该是AJAXCrawler对AJAX脚本的解析和DOM树的更新操作。因为AJAX-Crawler在关闭掉动态页面支持时, 速度跟普通Web Crawler相差不大。图4中的两条线几近平行, 表明两种爬虫此时的加速比也相差不多。而AJAXCrawler的加速上升趋势已开始走缓, 这就说明AJAXCrawler需要更多的资源。另外, 若对比下载的页面数, 两者相差了十余倍, 而下载速度却相对不是很大, 进一步说明了动态网页包含的内容丰富。

4 结束语

网络论坛爬虫设计 篇4

从号称“互联网金融元年”的2013年开始,“互联网+”的模式开始渗透到人们日常生活的方方面面,逐步影响着各个传统行业。如京东白条,就是一种新兴的网贷形式,通过追踪用户的消费行为来进行信用评级,最终确定借款额度,其本质是基于大数据的预测。从海量数据中挖掘真正的价值是一系列的处理过程目的,其第一步即是数据的获取,在Web 2.0的时代,大量可公开的数据均是通过网页形式进行展现的,网络爬虫作为一个通用的网页数据采集技术得到了广泛的应用。网络爬虫分为定向爬虫和广义爬虫,本文将介绍定向爬虫的实现和应用。

二、模块设计

本文介绍的网络爬虫采用开源Web应用程序测试工具Selenium来实现,Selenium完全由Java Script编写,因此可运行于任何支持Java Script的浏览器上。就像真正的用户在操作一样,无须用户去关注底层的网络通信协议细节,只要通过程序控制操作流程即可,大大节省了开发时间,方便可视化追踪整个执行流程。另外,因为采用User Agent模式,Selenium可直接绕过某些网页对广义爬虫抓取的限制。

(一)浏览器驱动模块

浏览器驱动模块,即利用Selenium来调用浏览器完成用户定义操作,目前Selenium支持以下几种操作。

1.启动浏览器

支持Chrome,Firefox,IE(可视化浏览器)、静默模式Phantom JS(只启动浏览器内核)或者远程驱动的方式。其中Firefox可以加载用户定制化的Profile等插件来提高对特殊应用的支持,另外可以获得当前URL的HTML信息,用于解析当前文档元素。

2.查找页面元素

支持通过XPath,CSS Selector等方式寻找指定页面元素,找到元素之后通过用户定义的过程来操作。

3.鼠标交互

支持mouse_over,ouse_out,click,double_click,drag_and_drop操作页面元素。

4.页面及表单交互

填充表单,下拉菜单选择,支持单选框和复选框,链接单击,获得元素值和状态。

获得当前页面包含的指定iframe,支持和alert及弹出窗口的交互,并可以在页面选项卡及窗口间跳转。

5.支持Java Script

目前支持基本的Java Script的语法,方便完成页面的异步操作。

6.Cookie管理器

添加、删除、返回所有当前浏览器支持的Cookie。

7.异常处理支持

目前支持驱动查找失败和页面元素查找失败的异常捕获。

(二)页面元素解析模块

页面元素解析模块采用Beautiful Soup来完成,它是一个从HTML或XML文件中提取数据的Python库,能够通过用户指定的转换器实现通用的文档浏览、查找和修改,从而大大节省开发时间。

Beautiful Soup通过将页面内容格式化为内存文档树的方式,提供了直接访问页面元素属性、子节点和遍历查找文档树的方式来完成文档相关的操作。

(三)验证码识别模块

验证码是用以区分用户是计算机还是人的公共全自动程序,可以防止恶意破解密码、刷票、论坛灌水,以及有效防止某个黑客对某一个特定注册用户用特定程序暴力破解的方式进行不断登录尝试。虽然验证码起到了保护作用,但是对于正常的爬虫程序来说,这一关如果无法绕过,则接下来的尝试都是没用的。

验证码识别是一个复杂的过程,涉及模式识别,一般复杂的验证码识别程序也是收费的,不能作为方便的插件嵌入到当前的程序中。而且并不是所有的验证码都可以通过程序来识别,本方案中采用Google的开源工具Tesseract-OCR来完成基础验证码识别,采用神经网络并利用样本集进行有监督的学习,Tesseract-OCR能较好地识别比较规范的数字英文字符串,如图1所示。

但是,对于有噪音及扭曲过的字符串识别效果很差,如图2所示。

所以,一般需要对图像进行预处理,然后再利用Tesseract-OCR来识别,这样可以取得较好的效果。

本项目中使用到的图像预处理技术有初步处理、清除噪点、清除干扰线、图像切割、字符标准化。

1.初步处理

初步处理包含:对比度处理、锐化、二值化。

(1)对比度处理

对比度,其实就是色差,增加对比度可以使亮的地方更亮,暗的地方更暗,从而使得验证码信息和噪音信息的区别更加明显。增强对比度的方案实际上就是将R,G,B通道乘以一个比例,这样就将相近颜色之间的差距变大,处理效果如图3所示。

(2)锐化

图像锐化处理的目的是使模糊的图像变得更加清晰。图像模糊实质就是受到平均或积分运算造成的,因此可以对图像进行逆运算来使图像清晰化。从频谱角度来分析,图像模糊的实质是其高频分量被衰减,因而可以通过高通滤波操作来清晰图像。但要注意,能够进行锐化处理的图像必须有较高的信噪比,否则锐化后图像信噪比反而更低,从而使噪音的增加比信号还要多。因此,一般做法是去除或减轻噪声后,再进行锐化处理。

图像锐化一般有两种方法:一种是微分法,另一种是高通滤波法,处理效果如图4所示。

(3)二值化

验证码的图像往往会加入杂色干扰,形成一个浓淡分布不均的多值图像。把这样一幅多灰度值的图像转化为只有黑(前景文字部分)和白(背景部分)分布的二值图像的工作叫做二值化处理。

一般来说,二值化方法可以分为:全局二值化和局部自适应二值化。全局二值化方法对每一幅计算一个单一的阀值。灰度级大于阀值的像素被标记为背景色,否则为前景。

局部二值化方法以像素的邻域信息为基础来计算每一个像素的阀值。其中一些方法还会计算整个图像中的一个阀值面。如果图像中一个像素的灰度级高于阀值面的计算值,那么把像素标记为背景,否则为前景字符。

常用的二值化方法包括:双峰直方图阀值分割法和平均灰度法,处理效果如图5所示。

2.清除噪点

图像去噪是数字图像处理中的重要环节和步骤,去噪效果的好坏直接影响后续的图像处理工作,如图像分割、边缘检测等。图像信号在产生、传输过程中都可能会受到噪声的污染,一般数字图像系统中的常见噪声主要有:高斯噪声、椒盐噪声等。

目前比较经典的图像去噪算法主要有以下3种。

均值滤波算法:也称为线性滤波,主要思想为邻域平均法,即用几个像素灰度的平均值来代替每个像素的灰度。它能有效抑制加性噪声,但容易引起图像模糊,可以对其进行改进,主要避开对景物边缘的平滑处理。

中值滤波:基于排序统计理论的一种能有效抑制噪声的非线性平滑滤波信号处理技术。中值滤波的特点是首先确定一个以某个像素为中心点的邻域,一般为方形邻域,也可以为圆形、十字形等,然后将邻域中各像素的灰度值排序,取其中间值作为中心像素灰度的新值。这里邻域被称为窗口,当窗口移动时,利用中值滤波可以对图像进行平滑处理。其算法简单,时间复杂度低,但对于点、线和尖顶多的图像,不宜采用中值滤波。

Wiener滤波:使原始图像和其恢复图像之间的均方差误差最小的复原方法,是一种自适应滤波器,根据局部方差来调整滤波器效果,对于去除高斯噪声效果明显。清除噪点效果如图6所示。

3.清除干扰线

一般验证码中会通过增加连续的干扰线来加大信息识别的难度,去除连续干扰线即识别出图像中的最大的连通线。基本思想是认为相邻的前景像素为一个连通线集合,通过递归和回溯法来寻找所有集合中最大的,即为最大连通线。清除连续干扰线效果如图7所示。

4.图像切割

对于去噪后的图像,需要对图片进行切割,切割的目的是为了提取信息,方便把图片中的数字转化为0,1形式的文本,方便后期利用Tesseract-OCR训练神经网络,进一步提高验证码的识别率。一般采用的切割方式是投影法,如图8所示。

如图8所示,对于切割数字3,首先需要找到垂线A和B,判断步骤是:纵向从左向右扫描图片,找到第一条含有信息点的直线记为A,继续向右扫描,从A开始找到第一条无信息点的直线记为B。从投影的角度来看,A与B之间X轴上的投影的信息值均大于0,切割A与B中间的图像后,以新图像为基础,找出C与D,至此便可切割出数字3。

获取了切割好的图像后,由于图像只有黑色与白色两种,因此遍历每一个像素点,根据像素点来进行0,1输出,一般认为黑色像素输出1,白色像素输出0。

5.字符标准化

标准化的意思是指对于图像中的字符尽量做到样式一致,以提高识别率。验证码的设计者往往会通过膨胀、旋转等方式来处理信息,增加识别难度。

(1)骨架细化:腐蚀算法

腐蚀算法的原理类似于剥洋葱,从最外层开始一层一层地将像素去掉,直到只剩下一层像素为止。腐蚀算法要借助凸包算法,用来找一堆像素点里面最外围的一层。腐蚀算法效果如图9所示。

(2)旋转卡壳算法

旋转卡壳算法主要用来处理旋转的字符,一般通过将单个字符左右各旋转一定度数范围来处理。每次1度,旋转后用扫描线法判断字符的宽度,对于标准的长方形字体,在完全垂直的时候肯定是宽度最窄的。旋转卡壳算法效果如图10所示。

经过上述两步处理后,还要将全部字符都缩到最小的字符一样大小来完成标准化处理。

6.样本训练

经过图像切割之后的矩阵包含了字符的相关信息,前景是1,背景是0,通过人工识别出相对应的字符。接着将这个矩阵转换为字符串,建立一个键值对,标明这串字符串是什么字符。之后只须多搜集几个同样字符的不同字符串变形,就能完成制作模版的过程。当搜集了足够多的模版后,就可以开始识别环节了。

通过构建神经网络,对上述字符串提取特征值,将其输入神经网络,再告诉它是什么字符,这样经过一定规模的训练之后,神经网络的内部结构会随之改变,逐渐向正确的答案靠拢,如图11所示。

利用神经网络识别的优势是,对于扭曲的字符识别成功率非常高。

三、总结

通过上述几个模块,就能搭建出一套完整的定向爬虫模型,该定向爬虫的优势有以下几点。

一是通过模拟浏览器操作,可以绕过大部分的网站对与连接数及IP访问限制的策略,大大扩展了爬虫可收集数据的范围。

二是验证码识别模块的增加使得一些门户网站登录的限制也被绕过。

然而,定向爬虫也有自身的缺陷,因为其跟网站页面结构的高度耦合性,如果页面结构发生修改,则对应的爬虫代码也要适当修改。针对上述缺陷,未来可能的一套方案是通过录制用户行为,自动记录、解析相关触发操作关联的页面元素,进而自动生成相关爬虫代码来适应页面结构的变化。

参考文献

[1]Gonzales RC,Woods RE.Digital Image Proeessing(Second Edition).Upper Saddle River:Prentice Hall,2002.

网络论坛爬虫设计 篇5

作为搜索引擎的基础构件之一, 网络爬虫 (Crawler) 直接面向互联网, 它是搜索引擎的数据来源, 决定着整个系统的内容是否丰富、信息能否得到及时更新[1,2]。它的性能表现直接影响整个搜索引擎的效果。该文使用Lucene.net平台设计实现了一个准确高效的网络爬虫。

1 Lucene简介

Lucene是一个信息检索的函数库 (Library) , 利用它可以为应用加上索引和搜索的功能。Lucene是一个工具, 可以把它理解为一个将索引, 搜索功能封装的很好的一套简单易用的API, 利用这套API可以做很多有关搜索的事情[3]。

Lucene.net是一个高性能的全文检索引擎, 而且免费开源, 几乎适合于任何需要全文检索的应用, 尤其是跨平台的应用, 它由Java下的Lucene移植而来, 在Java平台已经得到了广泛的应用[4,5]。

大部分的搜索 (数据库) 引擎都是用B树结构来维护索引, 索引的更新会导致大量的IO操作, Lucene在实现中, 对此稍微有所改进:不是维护一个索引文件, 而是在扩展索引的时候不断创建新的索引文件, 然后定期的把这些新的小索引文件合并到原先的大索引中 (针对不同的更新策略, 批次的大小可以调整) , 这样在不影响检索的效率的前提下, 提高了索引的效率[6]。

为了实现快速的搜索, Lucene会首先将需要处理的数据以一种称为倒排索引的数据结构进行存储。Lucene为需要被搜索的数据整理优化出一份索引文件 (Index file) , 而这个过程称之为“索引”。Lucene面向全文检索的优化在于首次索引检索后, 将所有结果中匹配度最高的头100条结果 (Top Docs) 的ID放到结果集缓存中并返回, 即使检索匹配总数很多, Lucene的结果集占用的内存空间也不会很多。如果首批缓存结果数用完后还要读取更后面的结果时Searcher会再次检索并生成一个上次的搜索缓存数大1倍的缓存, 并再重新向后抓取。

2 系统设计

2.1 需求分析

为了提高效率, 本系统应采用多线程抓取网页数据, 索引网页文字, 使用线程同步机制, 抓取数据与索引数据同时进行。本系统需有以下功能:

1) 爬虫系统初始化设置, 用户为爬虫设置开始爬去数据的开始地址, 爬取数据进程数, 索引数据进程数, url规则。

2) 爬虫系统可为特定url添加关键字, 当搜索到该关键字时, 该URL将优先显示出来。

3) 爬虫系统可设置访问深度, 即爬虫的垂直访问深度。

4) 爬虫系统可支持停止或继续抓取数据。

5) 爬虫系统可对已有索引文件进行优化索引, 提高查询速度。

6) 用户可优化索引。

2.2 系统逻辑结构

本系统采用分层设计, 结构清晰, 可扩展性强。系统主要分为:BLL业务逻辑层, DAL数据访问层, Model数据库实体层, Common层。其中BLL业务逻辑层主要实现数据抓取, 接受用户搜索, 页面分析等逻辑功能。DAL数据访问层主要负责处理所有涉及数据库的操作。Model数据库实体层主要为一些数据库实体层, 每个数据库表对应一个实体类。Common层主要包含一些常用类, 如:线程管理, Html页面分析, URL处理等类。

2.3 数据库设计

本系统所有数据按照Lucene.net特有索引文件格式存储到硬盘中。由于计算机存在少量也能够与数据处理, 数据需要长期保留在外村上反复进行查询、修改、插入和删除等操作。因此只将少量数据需要存储到数据库中, 本系统采用Microsoft SQL Server 2005做数据库。Wait For Index等待索引内容表, 该表主要存储爬虫程序停止后, 在内存中未索引数据存进数据库中。

3 系统实现

本系统采用四层结构, 分为界面层 (包括:web界面, Win Form界面) 、BLL业务逻辑层、DAL数据访问层、Common常用类、Model数据库实体层。

BLL业务逻辑层, 主要处理业务逻辑, 其中包括一些逻辑类、爬虫类、索引类、搜索类。DAL数据访问层通过使用.net中的反射机制实现ORM对象关系模型, 底层对数据库访问基类为Base DAL类, 该类使用.net中的泛型, 类似于C++中的模板机制, 从而使得该类可以接受任意类型的数据库实体类。该项目中对应Model层中的实体, 每个实体对应一个数据库访问类, 如Model层中有:Finished URL类, 则DAL层有Finished URLDAL类与之对应, 该类继承Base DAL类。Common层主要为一些常用类, 该系统中主要用到HTMLHelper类和Thread Manager类。HTMLHelper主要用于分析HTML页面信息, 获取URL列表, 页面Title、内容等。Thread Manager类为多线程管理类, 根据系统设置进行线程的启动, 停止操作。

3.1 后台模块设计

后台模块需要设置开始地址, 抓取数据线程数, 索引线程数, 访问深度, 链接规则等。其中:开始地址、抓数据线程数、索引线程数、访问深度为必填项。爬虫程序主界面如图1所示。

抓取数据模块主要是由BLL层中的Crawl类中的Start Crawler () 方法实现, 该类中的核心算法Start Crawler主要是对URLQueue进行出列, Pop出一个URL, 然后抓取该URL的数据, 将抓取的数据Push到content Queue中。

Start Crawler方法主要是对该类进行Pop以及Push操作, 当URLQueue长度大于10000条数据时, 则将其插入至数据库。

索引数据模块主要是由BLL层中的Index Page类中的Start Index () 方法实现, 该方法除了索引网页内容外, 同时还对已抓取网页进行分析, 提取网页中的URL, 标题, 关键字, 描述等信息。该类主要是对URLQueue和Content Queue进行操作, 该类的核心算法Start Index的程序流程图如下图所示, 当content Queue中元素大于5000条时则插入数据库。Start Index程序流程图如图2所示。

3.2 前台搜索设计

首页设计使用DIV+CSS布局方式。页面简单明了, 用户只需输入关键字, 点击“搜索”按钮即可, 程序将自动把搜索关键字POST到Show Result.aspx页面, 由该页面来查询数据并显示结果。搜索结果页面如图3所示。

3.4 初始化爬虫及索引管理

爬虫需要设置的参数主要有:访问开始地址、抓包线程数、索引线程数、访问深度、链接规则。访问开始地址为爬虫开始爬取数据的开始地址。由于该系统爬取数据与索引数据同时进行, 因此用户必须同时设置抓包线程数与索引线程数, 如果未设置则默认为一个线程。访问深度则设置爬虫爬取数据的深度。链接规则是设置爬虫只抓取该域名下的链接。使用Debug View捕捉到的程序运行状态如图4所示。

在本系统中使用多线程进行抓包以及索引数据, 每个索引线程建立一个索引目录, 如线程1则索引目录为:Thread1。多个线程将有多个索引目录, 搜索时候程序必然要读取所有目录, 这对于搜索来说照成了不便, 因此在程序主界面中有“优化索引”按钮, 该功能主要执行合并索引目录并优化索引, 提高搜索效率。

4 结束语

本文主要实现一个网页爬虫程序以及搜索程序。网页爬虫程序从某个网站节点开始, 采用广度遍历的方式, 运用多线程机制, 爬取网页信息, 在爬取网页的同时, 网页爬虫程序同时对已爬取数据进行分析, 提取有用文字信息, 并对这些信息建立索引。用户可为爬虫定义一些规则, 让爬虫只爬取特定的网页。爬虫也可为特定网站添加关键字, 当用户搜索该关键字时, 该网站将会优先显示。

参考文献

[1]NOVAK B.A survey of focused web crawling algorithms[c]//SIKDD2004at multiconference IS2004.Ljubljana, 2004.

[2]Ehng M, Maedche A.Ontology-focused crawling of Web documents[c]//Proc.of the2003ACM symposium on Applied computing.Flori-da, 2003.

[3]赵汀, 孟祥武.基于Lucene API的中文全文数据库的设计与实现[J].计算机工程与应用, 2003, 20:179-183.

[4]李晓明, 刘建国.搜索引擎技术及趋势[EB/OL].2008-04.http://www.xiye.cn/seo/523.html.

[5]张校乾, 金玉玲, 侯玉波.一种基于Lucene检索系统的一种全文数据库的设计与实现[J].现代图书情报技术, 2005 (2) :40-44.

网络论坛爬虫设计 篇6

关键词:进程,任务列表,ID,判重,任务转移,HASHTABLE

一、网络爬虫程序功能及原理概述

网络爬虫程序主要应用于网络搜索引擎中, 用于在互联网中收集数据, 为搜索引擎最主要的信息检索功能提供数据基础。网络爬虫程序效率的高低以及算法的优劣将直接影响搜索引擎的很多性能指标, 例如用户可以搜索到的信息量、搜索引擎数据库更新的周期等。爬虫配合数据挖掘工作可构建出基于大量数据的数据统计和管理, 这些数据对科研、工作、学习都会有很大帮助。

网络爬虫程序的主要功能是进行网页数据的抓取以及对网页中超链接的提取与分析。在程序初始时刻, 网络爬虫从一个可扩展的任务队列中提取一项任务, 即待抓取的网页信息 (URL以及标示该URL的文本信息等) , 随后将该URL对应的网页文件下载到本地, 对其中的HTML代码文本进行解析, 提取其中的链接及相关信息, 将提取的链接送入判重进程的队列中等待判重, 将未扩展过的URL及相关信息加入任务队列中, 等待扩展 (见图1) 。

二、分布式网络爬虫模型的体系结构概述

单个爬虫爬取的信息量是有限的, 且负载过重时会使整个模型处于不稳定状态, 所以可以考虑通过运行多个网络爬虫进程并行工作来收集数据, 因此就出现了分布式网络爬虫模型。

分布式网络爬虫模型主要考虑的问题有:1.任务分配;2.结束判定;3.扩展伸缩性。

如何进行任务分配呢?如果各个进程之间不通过某种方式的沟通协作, 必定出现多次爬取或回路爬取以及分布式数据存储器内数据不唯一。例如一个网页被爬取后存库, 另外一个爬虫重复爬取再次存库, 导致库中出现重复数据, 这在搜索引擎中是不允许的。所以需要一个单独的“判重”服务来负责判别数据是否重复。

对于结束的判定, 网络爬虫不多做考虑, 因为考虑到互联网中页面节点数超过10亿, 所以理想状况下将全部的10亿节点下载完毕的耗时将超过爬虫重新爬取的更新周期 (Google的爬虫更新周期为29天) 。当前爬虫进程工作全部完毕 (具体表示为当前进程的所有线程全部工作完毕处于等待状态) 后, 爬虫向当前Master进程申请任务, 继续扩展。Master进程内存储某一页面节点是否被爬取过, 以及被哪个爬虫爬取过, 这样做的好处是当某爬虫线程崩溃时方便任务的转移。

分布式网络爬虫模型的主要难点在于扩展伸缩性。爬虫系统需要考虑的主要问题有:1.单爬虫死亡;2.新爬虫加入;3.判重服务死亡。

新爬虫的加入和死亡只需与当前判重服务“打招呼”即可, 在获得判重服务分配的独特的ID后就可以开始工作。爬虫的死亡会在判重服务的链路检测中体现出来。判重服务在一定时间周期内可轮询每个爬虫, 若爬虫多次不响应即可判断此爬虫为“死亡”, 从而进行“任务转移”即可。

如果当前判重进程异常中止, 则需要从其它爬虫进程中通过选举, 产生一个新的判重进程, 新选举产生的进程通过数据收集, 重新建立与异常中止前状态相同的任务列表, 使整个系统能够持续稳定地运行。此时默认“已死”的爬虫爬取的任务已经转移给了别的“活着”的爬虫, 所以可以认为此时收集起来的任务列表与之前的任务列表完全相同。

另外应当注意的是, 由于分布式网络爬虫模型系统中没有固定的Master和Solve端, 所以一个爬虫进程应该具备从爬虫进程变为判重进程的能力 (不存在判重进程变为爬虫进程的情形, 那样花费过于昂贵且没有必要) 。

分布式模型示意图如图2:

三、分布式网络爬虫模型中运用的算法与数据结构分析

在一个互联的局域网内, 不同的进程运行在不同的终端上, 进程之间通过套接口进行数据交换。

当在局域网内某台终端上开始运行一个进程时, 该进程还不能确定自己的身份 (是爬虫进程还是判重进程) , 于是进程进行一次广播, 寻找当前判重进程。如果超时无响应, 则断定当前进程为该系统内第一个运行的进程, 于是进行判重进程的初始化工作 (建立收集任务列表等) , 使之成为判重进程。

如果接收到当前判重进程的回馈信息, 则进行爬虫进程的初始化工作, 成为爬虫进程, 回馈信息中包含判重进程所在终端的IP地址和用来唯一标识爬虫进程的ID, 该ID用来在将来的选举中标识身份。流程如图3:

1. 爬虫进程启动后的工作流程

启动为爬虫进程后, 初始化该进程的任务队列, 将保存在文件中的起始 (种子) URL加入任务队列 (如图4) 中, 读入起始任务队列的URL个数应大于默认启动的下载子线程个数, 随后启动默认个数的下载子线程, 下载子线程由不同的线程对象进行控制, 随后从任务队列中取出任务交给子线程进行扩展, 随即主线程进入监听状态, 根据子线程状态进行处理。

为了避免在扩展过程中对远程W e b服务器造成DDOS、收集到站点不希望收集的信息等一系列问题, 遵守Robots协议是良好的习惯。依据该站点的协议文件 (Robots.txt) , 对该站点禁入的目录予以回避, 于是在下载URL对应的网页之前, 需要首先下载当前URL所属站点的Robots协议文件 (Robots.txt) 进行分析, 提取规则, 将规则保存, 建立Robots协议规则缓存区, 待将来扩展该站点其他页面时使用。随后下载需扩展的网页, 存入当前线程的数据缓存区, 随后将自己挂起, 并标记挂起标志。

主线程对子线程的状态进行轮询, 当有子线程对象标记了挂起标志说明, 该子线程完成了下载任务, 主线程便对该线程下载的页面文本进行分析, 提取URL及URL信息, 将Robots协议规则允许扩展的URL提交判重进程进行判重, 如果判重进程回馈的信息表明该URL未被自己或其他进程扩展, 则存入当前进程的任务队列以待扩展。随后主线程从任务队列中取出新的任务, 分配给该子线程, 恢复其状态, 该子线程随即开始新的下载工作, 主线程则恢复轮询状态, 对其他子线程做相同的处理。

工作流程图见图5:

在爬虫进程工作过程中, 进程主要维护两个主要的数据结构, 任务队列类 (CLASS CLINK) 和子线程类 (CLASS CTHREAD) , 每个进程拥有一个CLINK实例, 存放已扩展和未扩展的任务, 负责任务调度, 所有进入队列的任务通过判重保证数据的全局唯一性, 其另一个作用是将已扩展任务信息提交给新选举产生的判重进程, 帮助其重构HASHTABLE。每个爬虫进程维护默认个数 (一般大于10) 的CTHREAD实例, 每个实例有自己的存储空间, 且可以对自身线程进行控制, 如挂起, 监视状态等。

2. 判重进程启动后的工作流程

判重进程的主要工作是维护HASHTABLE, 其中散列值是通过将URL字符串进行散列得出的, 散列算法使用北京大学李晓明、凤旺森在《两种对URL的散列效果很好的函数》一文中讨论分析的HFLP算法, 用以产生散列值, 该值与互联网中的URL串理论上是一一对应的, 可以用于判重工作。

判重进程的启动分为正常启动和选举启动, 正常启动发生在整个系统第一个运行的进程开始运行的时候;选举启动发生在当前判重进程异常中止后, 新的爬虫进程选举胜出成为新的判重进程并开始运行时。

(1) 判重进程正常启动过程

当判重进程正常启动后, 进行初始化工作, 如初始化HASHTABLE、爬虫进程ID数组、爬虫进程生存状态数组等, 初始化工作完成后便可进入监听状态。

当判重进程接收到新启动的工作进程 (未确定身份) 的广播消息后, 则发送回馈消息, 消息中包括当前判重进程的IP地址, 判重进程分配给它的ID号, 并通知其成为爬虫进程, 开始网页抓取工作。

判重进程接收最普遍的消息是爬虫进程发送的判重消息, 该消息中有某个URL串的散列值以及扩展该URL的爬虫进程的ID号, 判重进程根据散列值在HASHTABLE里的标记断定该URL是否被某个进程 (根据进程ID辨别) 扩展。

(2) 判重进程选举启动过程

判重进程的选举启动发生在当前判重进程异常中止后, 新的爬虫进程选举胜出成为新的判重进程并开始运行时。判重进程选举启动成功后, 最主要的任务是恢复原来状态 (当前判重进程异常中止前) 的HASHTABLE, 由于当前系统内各爬虫进程的任务队列中保存有其扩展过的任务信息, 因此可以从各爬虫进程端收集信息重构HASHTABLE。

判重进程选举启动成功后, 进行第一次消息广播, 通知各暂停工作的爬虫进程 (暂停工作及选举过程在下文详细叙述) 它的相关信息 (如IP) , 其他爬虫进程随即进行一次回应, 将自己的信息如IP地址, ID等信息回馈给判重进程, 判重进程随后依次 (次序为ID顺序) 向每个爬虫进程发送已扩展任务信息的收集通知, 并收集爬虫进程发送过来的信息用以重构HASHTABLE (对HASHTABLE进行重新标记) , 当重构工作完成后, 进行第二次广播, 通知各爬虫进程恢复工作, 随后判重进程进入监听状态, 以后的工作流程与正常启动后相同。

(3) 判重进程对某个爬虫进程异常退出后的处理

在整个爬虫构成的分布式系统模型中, 每个节点 (即爬虫进程终端) 具有独立性, 即某个节点的加入与撤出不会影响整个系统的正常工作, 这就需要判重进程对于记录在HASHTABLe中的某个已撤出 (关闭或异常退出) 的爬虫进程扩展的任务标记做出处理, 因为已经撤出的爬虫进程不再维护它本地的任务队列, 选举启动后的判重进程进行HASHTABLE重构时无法收集到已撤出的爬虫进程已扩展的任务信息, 于是将会在后续的工作中产生重复抓取的不良过程, 使得各个数据库中的信息不具有整体互联网数据集的一个划分性, 对搜索引擎的用户来说最直接的表现为重复信息的回馈, 这是不允许出现的, 因此判重进程需要监控爬虫进程的生存状况, 该工作通过维护一个爬虫进程生存状态数组 (以下简称状态数组) 来进行。

每当判重进程接收到一条爬虫进程的消息 (注册或者判重) , 就认定该爬虫进程是“活跃的”, 并在状态数组中进行标记, 随后每隔一个默认周期初始化一次状态数组, 如果某个爬虫进程对应的状态数组项在初始化之前判断没有发生改变 (即保持初始化状态) , 则对该爬虫进程“高度关注”, 如果下一个默认周期结束后状态仍无发生变化 (即爬虫进程未向判重进程发送任何消息) , 则断定该进程撤出 (关闭或异常退出) , 在随后的过程中将对该爬虫进程ID标示的HASHTABLE里的项进行特殊处理。

当其他爬虫进程针对某一个URL是否具有可扩展性向判重进程进行讯问的时候, 如果判重进程“意识到”被询问的U R L是一个已被撤出系统的爬虫进程扩展过的, 便通知前来询问的爬虫进程“不要扩展, 但不要丢弃, 存入你的已扩展队列”, 然后判重进程更改该URL在HASHTABLE中的爬虫进程ID, 将已撤出的爬虫进程ID更改为接替其保管该URL的爬虫进程的ID, 至此, 该URL扩展的“功劳”已经转移到一个“活跃”的爬虫进程的已扩展任务列表中, 保证其在以后的HASHTABLE重构收集过程中能被正常收集, 保证了其他进程不再对此已扩展的任务进行重复扩展。

四、结束语

网络论坛爬虫设计 篇7

搜索引擎是人们现在互联网冲浪必不可少的一项工具之一,常用的有百度、谷歌等老牌搜索引擎霸主,同时也不乏像搜狗、360搜索这样的新起之秀,各自都有自身优势,占有一定的市场份额,按分类来说都是属于综合性的搜索引擎,以满足各个方面的需求,而缺点是当需要找到某一行业的相关信息时,搜索引擎会同时罗列出行业以外的其他包含有关键字的网页,对于使用者来说必须根据自己的经验去鉴别,体验效果也会大打折扣;相比针对某一领域的垂直搜索引擎,其在搜索精度准度上能很好的把握,比如最近热火的商品比价购物网站如:阿里巴巴旗下的一淘网、网易旗下的惠惠网等,无论行业内外都有较高的影响力,为广大消费者提供了更加便捷的购物平台。而构建其平台的前提和关键技术就是网络爬虫,介绍以Heritrix体系构建的获取商品信息爬虫系统。

2 Heritrix网络爬虫系统

Heritrix是一款基于Java的开源的网络爬虫,由互联网档案馆和北欧国家图书馆联合规范化编写,第一次正式发布是在2004年1月,并不断的被完善和改进,其最出色之处在于良好的可扩展性,开发者可以扩展它的各个组件来实现自己的抓取逻辑,其工作流程为:从URI队列中选择一个URI,根据选定的URI下载远程文件,然后分析归档下载到的内容并写入磁盘镜像目录,再根据一定的策略从分析后的内容中选择URI加入URI队列,然后不断进行上述工作[1],Heritirx组件有:Crawl Order?(抓取任务)是整个抓取工作的起点,它记录了任务的所有属性,即在创建任务时的一系列设置;Crawl Controller(中央控制器)是抓取任务的核心组件,它控制着整个抓取的流程;Frontier?(链接制造工厂)负责所有链接的处理,将已经爬过的URI做标记,并将未处理的链接放入待处理队列;Toe Thread(处理线程)Heritirx是多线程的,每个URL?被一个线程处理,这个线程就叫做Toe Thread,每个线程都会包括一条处理链;Processor(处理器)负责下载网页,提取URI。它包括以下几种:Pre Processor(预处理器)、Fetcher(获取器)、Extractor(抽取器)、Writer(存储器)、Post Processor(后处理器)。

3 信息采集扩展

3.1 分析购物网站网址改进爬行策略

针对购物网站网址的特点,提前制定爬虫爬行策略,从而提高爬行的精度和效率,节省有限资源。以京东商城(http://www.360buy.com/)为例,浏览商城网页可以很清楚的发现整体网站的页面架构,以商品种类将网站分成若干子类,在网站根目录下存放的是商品各类别的主页面,如“家用电器”子站点是“http://www.360buy.com/electronic.html”,主页面是electronic.html;主页面内是商品为更加具体的列表类,如“家庭影院”其网址是“http://www.360buy.com/products/737-794-823.html”,其列表内特点是以目录products的形式存在;而最终产品终端页面如“三星HT-E453K”其网址是“http://www.360buy.com/product/628995.html”,分析其终端产品都存在于product的子目录下。由此京东商城的网站整体网址分布架构还是很清楚。

改进Heritrix爬行策略实现特定网页的抓取。FrontierScheduler存在于包org.archive.crawler.postprocessor中,其功能是将Extractor(抽取器)中所分析出的链接加入到Frontier?(链接制造工厂)中,以便后续处理。在该类中有一个名为inner Process(final Crawl URI curi)函数,该函数并未直接调用Frontier的schedule()方法,而是调用自己内部的schedule()方法,而这个方法中再调用Frontier的schedule()方法。这种调用方式为Frontier Scheduler的扩展留出接口。

我们首先构造一个Frontier Scheduler的子类Frontier Scheduler To360buy,这个类重载了schedule(Candidate URI ca Uri)这个方法,功能是限制抓取的URI必须包含“360buy.com/*.html”或“360buy.com/products/*.html”或“360buy.com/product/*.html”,以保证抓取的链接都是京东商城的产品主页、列表页或产品详细信息页。然后,在modules文件夹中的Processor.options中添加一行“org.archive.crawler.postprocessor.Frontier Scheduler To360buy|Frontier Scheduler To360buy”,这样在爬虫的Web控制台中就可以选择扩展的子类。

3.2 改进多线程爬取策略

Heritirx本身是多线程工作的,每个URL被一个线程处理,同时每个线程对应一条处理链。Heritirx是使用Berkely DB来构建链接队列,这些队列放置在Bdb Multiple Work Queues中以Key-Value形式存在的。URL被赋予Key值,Key值相同的链接放在同一个队列中。默认情况下Heritrix使用Hostname Queue Assignment Policy来来生成Key值。而这种策略是以Host名称为Key值方式实现的,即相同Host名称的所有URL都会被置放于同一个队列中,而这种方式对于单个网站抓取存在效率低的问题。因为在Heritrix中,一个线程从一个队列中取URL链接时,总是会先从队列的头部取出第一个链接,在这之后,这个被取出链接的队列会进入阻塞状态,不会被其他线程使用,直到该链接处理完才会恢复。

因此需要改变Key值的生成方式(queue-assignment-policy),使得所有的URL比较平均地散列到不同的队列中,以提高抓取效率。对应的方法是在Heritrix中扩展一个继承QueueAssignment Policy的子类,覆写其中的get Class Key()方法,该方法将一个链接对象处理后,再调用散列算法生成Key值。散列算法参考范先爽,刘东飞在文献“基于Heritrix网络爬虫算法的研究与应用”一文中采用ELFHash算法,可以将所有的URL散列到不同的队列中去,使所有的队列长度方差较小,保证工作线程的最大效率。实践证明,引入ELFHash算法后,抓取效率提高了很多。

4 结语

探讨了使用Heritirx框架的针对商品信息采集的策略,和改进采集方式的方法。同时也要清楚的认识制定采集策略也存在风险性,如因为URL结构过于复杂而无法制定合适的采集策略,或因为需要采集过多网站,而网站间的策略都不一致需要更多的人工干预。因此,如何提高采集策略的智能化,同时减少算法的复杂性,是今后需要解决的方向。

参考文献

[1]邱哲,符滔滔.Lucene2.0+Heritrix开发自己的搜索引擎.人民邮电出版社,2007.

[2]范先爽,刘东飞.基于Heritrix网络爬虫算法的研究与应用.

[3]姜鹏.主题网络爬虫系统的设计与实现,2010.

上一篇:审美价值论文下一篇:三寡头垄断市场