网络爬虫论文_第1页
网络爬虫论文_第2页
网络爬虫论文_第3页
网络爬虫论文_第4页
网络爬虫论文_第5页
已阅读5页,还剩38页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、摘要网络爬虫(Web Crawler),通常被称为爬虫,是搜索引擎的重要组成部分。随着信息技术的飞速进步,作为搜索引擎的一个组成部分网络爬虫,一直是研究的热点,它的好坏会直接决定搜索引擎的未来。目前,网络爬虫的研究包括Web搜索策略研究的研究和网络分析的算法,两个方向,其中在Web爬虫网络搜索主题是一个研究方向,根据一些网站的分析算法,过滤不相关的链接,连接到合格的网页,并放置在一个队列被抓取。把互联网比喻成一个蜘蛛网,那么Spider就是在网上爬来爬去的蜘蛛。网络蜘蛛是通过网页的链接地址来寻找网页,从网站某一个页面(通常是首页)开始,读取网页的内容,找到在网页中的其它链接地址,然后通过这些链

2、接地址寻找下一个网页,这样一直循环下去,直到把这个网站所有的网页都抓取完为止。如果把整个互联网当成一个网站,那么网络爬虫就可以用这个原理把互联网上所有的网页都抓取下来。关键词:网络爬虫;Linux Socket;C/C+;多线程;互斥锁AbstractWeb Crawler, usually called Crawler for short, is an important part of search engine. With the high-speed development of information, Web Crawler- the search engine can not l

3、ack of- which is a hot research topic those years. The quality of a search engine is mostly depended on the quality of a Web Crawler. Nowadays, the direction of researching Web Crawler mainly divides into two parts: one is the searching strategy to web pages; the other is the algorithm of analysis U

4、RLs. Among them, the research of Topic-Focused Web Crawler is the trend. It uses some webpage analysis strategy to filter topic-less URLs and add fit URLs into URL-WAIT queue.The metaphor of a spider web internet, then Spider spider is crawling around on the Internet. Web spider through web link add

5、ress to find pages, starting from a one page website (usually home), read the contents of the page, find the address of the other links on the page, and then look for the next Web page addresses through these links, so has been the cycle continues, until all the pages of this site are crawled exhaus

6、ted. If the entire Internet as a site, then you can use this Web crawler principle all the pages on the Internet are crawling down.Keywords:Web crawler;Linux Socket;C/C+; Multithreading;Mutex目 录摘要I第一章 概 述11.1 课题背景11.2 网络爬虫的历史和分类11.2.1 网络爬虫的历史11.2.2 网络爬虫的分类21.3 网络爬虫的发展趋势31.4 系统开发的必要性31.5 本文的组织结构3第二章

7、相关技术和工具综述52.1 网络爬虫的定义52.2 网页搜索策略介绍52.2.1 广度优先搜索策略52.3 相关工具介绍62.3.1 操作系统62.3.2 软件配置6第三章 网络爬虫模型的分析和概要设计83.1 网络爬虫的模型分析83.2 网络爬虫的搜索策略83.3 网络爬虫的概要设计10第四章 网络爬虫模型的设计与实现124.1 网络爬虫的总体设计124.2 网络爬虫的具体设计124.2.1 URL类设计及标准化URL124.2.2 爬取网页134.2.3 网页分析144.2.4 网页存储144.2.5 Linux socket通信164.2.6 EPOLL模型及其使用204.2.7 POS

8、IX多线程及其使用22第五章 程序运行及结果分析255.1 Makefile及编译255.2 运行及结果分析26第六章 总结与展望30致 谢31参考文献32第一章 概 述1.1 课题背景网络爬虫,是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁,自动索引,模拟程序或者蠕虫。网络检索功能起于互联网内容爆炸性发展所带来的对内容检索的需求。搜索引擎不断的发展,人们的需求也在不断的提高,网络信息搜索已经成为人们每天都要进行的内容.如何使搜索引擎能时刻满足人们的需求。最初的检索功能通过索引站的方式实现,而有了网络机器人,即网络爬虫这个技术之后,搜索引擎的时代便开始

9、一发不可收拾了。1.2 网络爬虫的历史和分类 网络爬虫的历史在互联网发展初期,网站相对较少,信息查找比较容易。然而伴随互联网爆炸性的发展,普通网络用户想找到所需的资料简直如同大海捞针,这时为满足大众信息检索需求的专业搜索网站便应运而生了。现代意义上的搜索引擎的祖先,是1990年由蒙特利尔大学学生Alan Emtage发明的Archie。虽然当时World Wide Web还未出现,但网络中文件传输还是相当频繁的,而且由于大量的文件散布在各个分散的FTP主机中,查询起来非常不便,因此Alan Archie工作原理与现在的搜索引擎已经很接近,它依靠脚本程序自动搜索网上的文件,然后对有关信息进行索引

10、,供使用者以一定的表达式查询。由于 Archie深受用户欢迎,受其启发,美国内华达System Computing Services大学于1993年开发了另一个与之非常相似的搜索工具,不过此时的搜索工具除了索引文件外,已能检索网页。当时,“机器人”一词在编程者中十分流行。电脑“机器人”(Computer Robot)是指某个能以人类无法达到的速度不间断地执行某项任务的软件程序。由于专门用于检索信息的“机器人”程序象蜘蛛一样在网络间爬来爬去,因此, 搜索引擎的“机器人”程序就被称为“蜘蛛”程序。世界上第一个用于监测互联网发展规模的“机器人”程序是Matthew Gray开发的World wide

11、 Web Wanderer。刚开始它只用来统计互联网上的服务器数量,后来则发展为能够检索网站域名。与Wanderer相对应,Martin Koster于1993年10月创建了ALIWEB,它是Archie的HTTP版本。ALIWEB不使用“机器人”程序,而是靠网站主动提交信息来建立 自己的链接索引,类似于现在我们熟知的Yahoo。随着互联网的迅速发展,使得检索所有新出现的网页变得越来越困难,因此,在Matthew Gray的Wanderer基础上,一些编程者将传统的“蜘蛛”程序工作原理作了些改进。其设想是,既然所有网页都可能有连向其他网站的链接,那么从跟踪一个网站的链接开始,就有可能检索整个互

12、联网。到1993年底,一些基于此原理的搜索引擎开始纷纷涌现,其中以Jump Station、The World Wide Web Worm(GoTo的前身,也就是今天Overture),和Repository-Based Software Engineering (RBSE) spider最负盛名。然而Jump Station和WWW Worm只是以搜索工具在数据库中找到匹配信息的先后次序排列搜索结果,因此毫无信息关联度可言。而RBSE是第一个在搜索结果排列中引入关键字串匹配程 度概念的引擎 最早现代意义上的搜索引擎出现于1994年7月。当时Michael Mauldin将John Leavi

13、tt的蜘蛛程序接入到其索引程序中,创建了大家现在熟知的Lycos。同年4月,斯坦福(Stanford)大学的两名博士生,David File和美籍华人杨致远(Gerry Yang)共同创办了超级目录索引Yahoo,并成功地使搜索引擎的概念深入人心。从此搜索引擎进入了高速发展时期。目前,互联网上有名有姓的搜索引擎已达数百家,其检索的信息量也与从前不可同日而语。比如最近风头正劲的Google,其数据库中存放的网页已达30亿之巨。随着互联网规模的急剧膨胀,一家搜索引擎光靠自己单打独斗已无法适应目前的市场状况,因此现在搜索引擎之间开始出现了分工协作,并有了专业的搜索引擎技术和搜索数据库服务提供商。像国

14、外Inktomi,它本身并不是直接面向用户的搜索引擎,但向包括Overture(原GoTo)、 LookSmart、MSN、HotBot等在内的其他搜索引擎提供全文网页搜索服务。国内的百度也属于这一类(注),搜狐和新浪用的就是它的技术。因此 从这个意义上说,它们是搜索引擎的搜索引擎。1.2.2 网络爬虫的分类网络爬虫种类繁多,如果按照部署在哪里分,可以分成:(1)服务器侧:一般是一个多线程程序,同时下载多个目标HTML,可以用PHP, Java, Python等做,一般综合搜索引擎的爬虫这样做。但是,如果对方讨厌爬虫,很可能封掉服务器的IP,服务器IP又不容易改,另外耗用的带宽也是较贵。(2)

15、客户端:很适合部署定题爬虫,或者叫聚焦爬虫。做一个与Google,百度等竞争的综合搜索引擎成功的机会微乎其微,而垂直搜索或者比价服务或者推荐引擎,机会要多得多,这类爬虫不是什么页面都取的,而是只取关心的页面,而且只取页面上关心的内容,例如提取黄页信息,商品价格信息,还有提取竞争对手 广告信息的。这类爬虫可以部署很多,而且可以很有侵略性。可以低成本大量部署,由于客户端IP地址是动态的,所以很难被目标网站封锁。1.3 网络爬虫的发展趋势目前,大多数的搜索引擎都是基于关键词的搜索引擎。基于关键字匹配的搜索技术有较大的局限性:首先,它不能区分同形异义。其次,不能联想到关键字的同义词。Web商业化至今,

16、搜索引擎始终保持着网络上被使用最多的服务项目的地位,然而,随着网上内容的爆炸式增长和内容形式花样的不断翻新,搜索引擎越来越不能满足挑剔的网民们的各种信息需求。搜索引擎的发展面临着两大难题:一是如何跟上Internet的发展速度,二是如何为用户提供更精确的查询结果。所以,传统的引擎不能适应信息 技术的高速发展,新一代智能搜索引擎作为一种高效搜索引擎技术的在当今的网络信息时代日益引起业界人士的关注。搜索引擎己成为一个新的研究、开发领域。因 为它要用到信息检索、人工智能、计算机网络、分布式处理、数据库、数据挖掘、数字图书馆、自然语言处理等多领域的理论和技术,所以具有综合性和挑战性。又 由于搜索引擎有

17、大量的用户,有很好的经济价值,所以引起了世界各国计算机科学界和信息产业界的高度关注,目前的研究、开发十分活跃,并出现了很多值得注意的动向。1.4 系统开发的必要性爬虫程序是一个自动获取网页的程序。它为搜索引擎从互联网上下载网页,是搜索引擎的重要组成部分。爬虫程序的实现策略,运行效率直接影响搜索引擎的搜索结果。不同的搜索引擎,会根据对搜索结果的不同需求,选择最合适的爬行策略来搜集互联网上的信息。高效,优秀的爬虫程序可以使人们在互联网上寻找到更及时,更准确的信息。而现在Linux平台下开源的搜索引擎资料较少,作为实现最终开发目标搜索引擎的一部分,本爬虫程序可以为搜索引擎提供良好的网页获取能力,并可

18、以为在Linux下开发网络爬虫的后来者提供参考。1.5 本文的组织结构本文主要根据网络爬虫的特点,结合搜索引擎关键技术,linux网络编程,对爬虫程序的关键技术做了详细的分析和研究。然后设计并实现了一个以抓取相关关键字内容并实现离线浏览功能的网络爬虫系统。本文主要分为6个章节,结构安排如下:(1)绪论,对课题的背景研究意义和爬虫的研究现状做了简单介绍。(2)相关技术和工具介绍。对网络爬虫的定义、评价指标分类、工作原理并对开发环境和工具进行了简单介绍。并以此引出网络爬虫系统的相关知识介绍。(3)网络爬虫的模型分析 。对网络爬虫视线中的主要思想以及关键技术进行了具体的分析。(4)网络爬虫的模型设计

19、 根据第三章内容。对爬虫系统进行了详细设计,并对本爬虫系统的模型实现进行具体分析。同时也对使用的技术进行简单的介绍。(5)程序运行和结果分析对程序的编译运行进行简单介绍。并对测试结果进行了简单分析。(6)总结和展望。第二章 相关技术和工具综述2.1 网络爬虫的定义定义1:网络爬虫是一个自动提取网页的程序,它为搜索引擎从Web上下载网页,是搜索引擎的重要组成部分。通用网络爬虫从一个或若干初始网页的URL开始,获得初始网页上的URL列表;在抓取网页的过程中,不断从当前页面上抽取新的URL放入待爬行队列,直到满足系统的停止条件。定义2:网络爬虫就是根据一定的网页分析算法过滤与主题无关的链接,保留相关

20、的链接并将其放入待抓取的URL队列中;然后根据一定的搜索策略从队列中选择下一步要抓取的网页URL,并重复上述过程,直到达到系统的某一条件时停止。所有被网络爬虫抓取的网页将会被系统存储,进行一定的分析、过滤,并建立索引,对于网络爬虫来说,这一过程所得到的分析结果还可能对后续的抓取过程进行反馈和指导。定义3:如果网页p中包含超链接l,则p称为链接l的父网页。定义4:如果超链接l指向网页t,则网页t称为子网页,又称为目标网页。网络爬虫的基本思路就是按照事先给出的主题,分超链接和已经下载的网页内容,预测下一个待抓取的URL及当前网页的相关度,保证尽可能多地爬行、下载相关的网页,尽可能少地下载无关网页。

21、2.2 网页搜索策略介绍网页的抓取策略可以分为深度优先、广度优先和最佳优先三种。深度优先在很多情况下会导致爬虫的陷入(trapped)问题,目前常见的是广度优先和最佳优先方法。2.2.1 广度优先搜索策略广度优先搜索策略是指在抓取过程中,在完成当前层次的搜索后,才进行下一层次的搜索。该算法的设计和实现相对简单。在目前为覆盖尽可能多的网页,一般使用广度优先搜索方法。也有很多研究将广度优先搜索策略应用于聚焦爬虫中。其基本思想是认为与初始URL在一定链接距离内的网页具有主题相关性的概率很大。另外一种方法是将广度优先搜索与网页过滤技术结合使用,先用广度优先策略抓取网页,再将其中无关的网页过滤掉。这些方

22、法的缺点在于,随着抓取网页的增多,大量的无关网页将被下载并过滤,算法的效率将变低。2.3 相关工具介绍2.3.1 操作系统本网络爬虫程序开发环境为Linux CentOS操作系统,并且目标是在Linux下运行,而在其他平台上会出现各种无法正常运行的问题,所以在此有必要介绍一下该程序的运行环境,Linux操作系统。Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的UNIX工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网

23、络操作系统。而Linux主要作为Linux发布版(通常被称为"distro")的一部分而使用。Linux发布版指的就是通常所说的“Linux操作系统”,它可能是由一个组织,公司或者个人发布的。通常来讲,一个Linux发布版包括Linux内核,将整个软件安装到计算机上的一套安装工具,各种GNU软件,其他的一些自由软件,在一些特定的Linux发布版中也有一些专有软件。发布版为许多不同的目的而制作,包括对不同计算机硬件结构的支持,对一个具体区域或语言的本地化,实时应用,和嵌入式系统。目前,超过三百个发布版被积极的开发,最普遍被使用的发布版有大约十二个。较为知名的有Fedora,U

24、buntu,Mageia,红旗Linux,CentOS等。本程序所使用的开发操作系统是Linux中比较知名的CentOS。2.3.2 软件配置在CentOS Linux中,本文主要用的开发软件是Vim。一般Linux的发行版都自带Vim,Vim是个可配置性极强的文本编辑器,可以进行高效的文本编辑。 Vim常被称作“程序员的编辑器”,其功能如此强大以致许多人认为它就是个完整的IDE。当然,它并不仅仅为程序员而生。面对各种文本编辑,无论是撰写email还是编辑配置文件,Vim都臻于完美。但是只有你自己配置之后才能变成适合于你自己的开发工具。所以需要修改Vim的配置文件,常用的有(以下为简

25、单配置):“不要使用vi的键盘模式,而是vim自己的:set nocompatiblehistory文件中需要记录的行数:set history=100“语法高亮:syntax on“为C程序提供自动缩进:set smartindent“使用C样式的缩进:set cindent“制表符为4:set tabstop=4“统一缩进为4:set softtabstop=4 set shiftwidth=4还有一点不能忽视,那就是安装GCC编译器,因为本文写的所有代码都是C/C+格式的。虽说基本上每个发行版都已经安装了GCC编译器,但不是很全,为了以防万一,在终端下执行了以下命令:$ yum y in

26、stall gcc$ yum y install gcc-c+$ yum install make-或者执行$ yum groupinstall “Development Tools”-或者执行$ yum install gcc gcc-c+ kernel -develGCC下编译.c文件:gcc o xx xx.c,编译.cpp文件只需把gcc改为g+即可。在多文件编译的情况下,这样的命令会很繁琐,通常会写一个或多个Makefile文件来解决这个问题,在本文的最后会讲到。第三章 网络爬虫模型的分析和概要设计3.1 网络爬虫的模型分析网络爬虫框架参考的是一个叫larbin的开源爬虫,它是由法国

27、的年轻人Sebastien Ailleret独立开发,用C+语言实现,其代码可以直接在网上可以下载到。以下是本程序爬虫使用的框架,看起来更像是主题爬虫的框架。如图3.1所示。图 3-1 网络爬虫的基本框架图首先建立URL任务列表队列,即开始要爬取的URL。由URL任务列表开始,根据预先设定的深度爬取网页,同时判断URL是否重复,按照一定算法和排序方式搜索页面,然后对页面按照一定算法进行分析,并提取相关URL,最后将所得URL返回任务列表队列。之后将任务列表中URL重新开始爬取,从而使网络爬虫进行循环工作。3.2 网络爬虫的搜索策略本文的搜索策略为广度优先搜索策略。如下图3-2所示。搜索过程为a

28、bcdefghijklmnop这样一个顺序。图3-2 广度优先搜索策略示意图(1)定义一个状态结点采用广度优先搜索算法解答问题时,需要构造一个表明状态特征和不同状态之间关系的数据结构,这种数据结构称为结点。不同的问题需要用不同的数据结构描述。(2)确定结点的扩展规则根据问题所给定的条件,从一个结点出发,可以生成一个或多个新的结点,这个过程通常称为扩展。结点之间的关系一般可以表示成一棵树,它被称为解答树。搜索算法的搜索过程实际上就是根据初始条件和扩展规则构造一棵解答树并寻找符合目标状态的结点的过程。广度优先搜索算法中,解答树上结点的扩展是沿结点深度的“断层”进行,也就是说,结点的扩展是按它们接近

29、起始结点的程度依次进行的。首先生成第一层结点,同时检查目标结点是否在所生成的结点中,如果不在,则将所有的第一层结点逐一扩展,得到第二层结点,并检查第二层结点是否包含目标结点 对长度为n+1的任一结点进行扩展之前,必须先考虑长度为n的结点的每种可能的状态。因此,对于同一层结点来说,求解问题的价值是相同的,我们可以按任意顺序来扩展它们。这里采用的原则是先生成的结点先扩展。结点的扩展规则也就是如何从现有的结点生成新结点。对不同的问题,结点的扩展规则也不相同,需要按照问题的要求确定。(3)搜索策略为了便于进行搜索,要设置一个表存储所有的结点。因为在广度优先搜索算法中,要满足先生成的结点先扩展的原则,所

30、以存储结点的表一般设计成队列的数据结构。搜索的步骤一般是:(1)从队列头取出一个结点,检查它按照扩展规则是否能够扩展,如果能则产生一个新结点。(2)检查新生成的结点,看它是否已在队列中存在,如果新结点已经在队列中出现过,就放弃这个结点,然后回到第(1)步。否则,如果新结点未曾在队列中出现过,则将它加入到队列尾。(3)检查新结点是否目标结点。如果新结点是目标结点,则搜索成功,程序结束;若新结点不是目标结点,则回到第(1)步,再从队列头取出结点进行扩展。最终可能产生两种结果:找到目标结点,或扩展完所有结点而没有找到目标结点。3.3 网络爬虫的概要设计本网络爬虫的开发目的,通过网络爬虫技术一个自动提

31、取网页的程序,实现搜索引擎从自己想要访问的网上下载网页,再根据已下载的网页上继续访问其它的网页,并将其下载直到满足用户的需求。根据现实中不同用户的实际上的各种需求,本项目简单实现主题爬虫,本网络爬虫需要达到如下几个目标:(1)设计基于多线程的网络爬虫,客户端向服务器发送自己设定好请求。如图3-3所示。图3-3 多线程网络爬虫概要设计图模型(2)通过 http将Web服务器上协议站点的网页代码提取出来。(3)根据一定的正则表达式提取出客户端所需要的信息。(4)广度优先搜索可从网页中某个链接出发,访问该链接网页上的所有链接,访问完成后,再通过递归算法实现下一层的访问。本网络爬虫最终将设计成一个能够

32、自动读写配置文件并且在后台自动执行的网络爬虫程序。网络爬虫工作流程图如图3-4所示。图3-4 网络爬虫工作流程图第四章 网络爬虫模型的设计与实现4.1 网络爬虫的总体设计根据本网络爬虫的概要设计本网络爬虫是一个自动提取网页的程序,根据设定的主题判断是否与主题相关,再根据已下载的网页上继续访问其它的网页,并将其下载直到满足用户的需求。(1)设计基于多线程的网络爬虫。(2)通过 http协议将待爬取URL列表对应的URL的网页代码提取出来。(3)提取出所需要的信息并且通过算法判断网页是否和设定的主题相关。(4)广度优先搜索,从网页中某个链接出发,访问该链接网页上的所有链接,访问完成后,再通过递归算

33、法实现下一层的访问,重复以上步骤。总的来说爬虫程序根据输入获得URL任务列表,即初始URL种子,把初始种子保存在临界区中,按照广度搜索运算法搜索抓取网页并提取URL返回到临界区中,通过判断主题相关度算法判断相关度,取出不相关网页,从而使整个爬虫程序循环运行下去。4.2 网络爬虫的具体设计4.2.1 URL类设计及标准化URLURL 的一般形式是:<URL的访问方式>:/<主机>:<端口>/<路径>。为了方便处理,设计了一个名叫URL的类,它包含Host(主机名),Port(端口),File(文件路径),Fname(给这张网页取的名字)。以下代码是

34、class URL的成员及其成员函数(摘自web.h):class URLpublic:URL() void SetHost(const string& host) Host = host; string GetHost() return Host; void SetPort(int port) Port = port; int GetPort() return Port; void SetFile(const string& file) File = file; string GetFile() return File; void SetFname(const string&

35、amp; fname) Fname = fname; string GetFname() return Fname; URL() private:string Host;int Port;string File;string Fname;对URL的处理:此外,注意到在网页源代码中,URL有些是绝对路径,有些是相对路径,还有一些URL中存在字符#,多个/等等。因此,需要对这些URL进行处理,分别得到每个URL的Host,Port,File。以下是本文对URL的设定:(1)URL的File成员不能以/结尾,若有则以0填充;若该File成员没有路径,则设定其路径为/。这样做的目的是为了便于URL排重

36、。(2)URL的File成员中若有#字符,则删除它及它以后的字符,剩余的字符串作为File的值。(3)若URL中没有显式表明端口,则默认Port成员的值为80。(4)若URL没有主机属性,则默认Host成员的值为初始URL的主机名。4.2.2 爬取网页在分析网页之前,首先网页需要被抓取下来,分析一下数据从服务器保存到本地的过程。第一部分:分析之前,首先要明确的是:当从sockfd读取数据时,最前面一部分是和网页本身无关的信息,比如有些网页未找到,就会返回404 not found等服务信息,类似的,每种情况会返回对应的信息,因此,对于一些服务信息,应该不予记录。当读到>字符时才开始正式记

37、录网页内容。第二部分:定义一个tmp的字符数组,用来临时存放抓取的的网页,抓取方法与第一部分相同同,都是用read函数,不同的是这里是一块一块抓取,效率上能比每次抓取一个字节要高。有人可能会问,为什么不直接存放到文件中,而要保存到临时数组中呢?解释是:因为下一步分析网页时,有个URL重定向的过程,程序还会继续修改tmp数组。如果直接保存到文件,那么还得再次打开文件分析网页,这样会降低效率,因为在磁盘执行读写操作总是比在内存读写慢得多。4.2.3 网页分析(1)URL提取考虑到网页中的链接格式主要是:<a herf=”xxx”>title</a>,因此本文通过string

38、自身封装的find函数来找到每一个”herf”的位置,接下来的情况稍微有些复杂,分为三种情况。第一种:URL用双引号引起来;第二种:以单引号引起来;第三种:URL没有被引起来。在此使用了一个标记变量(flag)来区分以上三种情况。(2)URL的重定向考虑到本文的要求不仅仅是抓取网页本身,还要实现一个离线浏览网页的功能,原有的链接不再有效,因此,URL的重定向这一步不可缺少。之前,爬虫已经抓取了一些网页并存放在了一个名为Pages的文件夹中,而且其中的每个网页都进行了重命名处理(本文直接以url.Fname的字符串哈希值作文保存网页的文件名)。那么在本地的URL无论在路径和文件名上都和原来网页上

39、的链接都是不对应的,要想实现和原来一样的网页跳转,必须修改每个链接的herf值。对于原来的链接<a herf=”xxx.html”>title</a>,假设现在重命名该网页为new.html,那么如何处理怎么才能转化成新的链接呢?方法有很多,比如可以通过覆盖和移动,使得两个引号直接的内容为new.html。本文采用的方法如下:现已知第一个引号的位置为pos_1,因此可以调用string类的insert方法。调用后的效果如下:<a herf=”new.html” ”xxx.html”>title</a>这样处理不仅屏蔽了”xxx.html”,也避免

40、了删除原有链接等不必要操作,一定程度上提高了代码的效率。(3) URL判重抓取网页时有一个非常棘手的问题,那就是重复抓取问题。大家知道,一个网站中的链接非常多,抽象出来就是一个巨大的蜘蛛网,类似与图论中的无向图。如果不对爬虫进行设置,它就像一只无头苍蝇一样,到处乱撞。这样待抓取队列里的URL越来越多,并且好多都是重复的。那么如何才能跳出这个怪圈呢?C+已经为大家提供了一个叫set的容器(当然也可以使用hash来判重)。在cplusplus这样介绍:set是一种存放唯一性元素的关联容器,它里面的每一个元素都称为关键字,它由二叉搜索树实现。由于它的唯一性,高效性,把它选择作为URL判重的一种类似h

41、ash的工具。本文代码如下:定义:set<unsigned int>Set;使用:Set.insert(hashVal);4.2.4 网页存储前面爬虫已经抓取到了一张网页,并且进行了重定向处理。那么接下来要做的事就是把它保存到磁盘里,在这一步需要用到文件操作(摘自http.cpp)。chdir("Pages");int fd = open(url_t.GetFname().c_str(), O_CREAT|O_EXCL|O_RDWR, 00770);/* check whether needs re-fetch */if(fd < 0) if(errno

42、= EEXIST) stat(url_t.GetFname().c_str(), &buf);int len = buf.st_size;if(len >= flen) goto NEXT;else fd = open(url_t.GetFname().c_str(), O_RDWR|O_TRUNC, 00770);if(fd < 0) perror("file open error"); goto NEXT; else perror("file open error");goto NEXT;write(fd, HtmFile.c_s

43、tr(), HtmFile.length();NEXT:close(fd);/ todo next以上代码主要功能是保存已抓取网页的内容到磁盘。有时候在网络状况不理想的情况下,爬虫抓取有些网页时会导致请求超时,或抓取内容不全,因此为了完善抓取内容,可以进行下一次重复抓取,其抓取条件为:该文件不存在,则直接进行抓取;该文件已经存在且当前抓取的内容多与上次抓取的,则覆盖上次保存的文件;其它情况,放弃。第一行代码使用O_CREAT | O_EXCL | O_RDWR模式打开,当该文件已经存在时返回-1,错误代码存放在error中,错误代号为EEXIST。代码中使用stat函数来读取参数为文件名的文件

44、信息,其中我们需要的就是st_size这个成员的内容,它以字节形式记录了文件的大小。这样就可以与当前抓取网页大小(存放于变量flen中)比较,从而判断是否需要覆盖原有文件。本文以上代码虽然使用了不推荐的goto语句,因为程序需要跳过write函数。不过使用goto语句在没有给程序带来混乱的情况下实现了一条break语句实现不了的功能,因此更具实用性。4.2.5 Linux socket通信本文中的socket通信基于TCP,因此有必要提一下TCP的连接和断开过程。TCP的可靠连接得益于它的三次握手原理,下图形象的表示了TCP三次握手建立连接和两次半关闭断开连接的具体过程。在连接和断开连接之间,

45、客户端和服务器即可进行双向的信息通信。图4-1 TCP三次握手与两次半关闭过程在了解各个Socket函数之前,首先来看一个经典的流程图,几乎每次网络通信都需要走以下流程,它详细地显示了TCP客户端和TCP服务器之间的Socket通信流程:图4-2 基于TCP客户/服务器程序的套接字函数及通信流程在程序中,每一个URL对应的网页,在客户端都需要完成Socket(),Connect(),Write(),Read(),Close()这一过程。要注意的是,如果不及时关闭Socket文件描述符,有时会出现“open too many files”的系统错误,这是由于系统对用户同时打开多个文件的限制(这里

46、的文件不仅仅指通常意义上的文件,Linux会把任何东西都当做文件,包括目录、各类描述符等)。而且,以上情况在多线程情况下特别容易出现。(1)socket() 函数要进行网络I/O操作,第一件要做的事就是调用socket()函数。该函数用来产生一个int类型的socket文件描述符,函数原型:#include <sys/socket.h>int socket(int family, int type, int protocal);返回:若成功则返回非负描述符,否则返回-1。参数: family指明协议族,有AF_INET,AF_INET6等。type指明套接字类型,有SOCK_STR

47、EAM,SOCK_DGRAM等。protocol指明某个协议类型,常设为0。例(摘自http.cpp):if(sockfd = socket(PF_INET, SOCK_STREAM, 0) = -1) return -1;至于本文为什么采用PF_INET而不是AF_INET,是因为POSIX下对应PF_INET,BSD中对应AF_INET。两者版本不同,但差别微小。(2)connect() 函数TCP客户端用connect()函数来建立与TCP服务器的连接,在连接之前,需要对该函数第二个参数进行初始化操作。函数原型7:#include <sys/socket.h>int conn

48、ect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);返回:成功返回0,反之返回-1参数:sockfd是由socket函数返回的套接字描述符第二、第三个参数分别是一个指向套接字地址结构的指针和该结构的大小,其初始化代码如下(摘自http.cpp):struct sockaddr_in server_addr;bzero(&server_addr, sizeof(server_addr);server_addr.sin_family = AF_INET;server_addr.sin_port = hton

49、s(80); server_addr.sin_addr = *(struct in_addr *)Host->h_addr); 在本例子中,没有在调用connect函数之前调用bind函数(用来绑定端口等地址信息),因为在客户端下除非不是特殊情况,无须调用。例(摘自http.cpp)if(connect(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr) = -1) perror("connect error");return -1;(3)write(), read() 函数本文

50、使用这两个函数来读写套接字操作,read函数从参数fd读取内容放到参数buf中;相反,write函数把参数buf的内容写入到参数fd中。#include <unistd.h>ssize_t read(int fd, void * buf , size_t count);返回:返回实际读到的字节数,出错返回-1,错误信息存放在errno中。参数:fd为文件描述符;第二个指定要读入的buf指针指向的内存,第三个参数表明要读取的字节数。#include<unistd.h>ssize_t write (int fd, const void * buf, size_t count

51、);返回:返回实际写入的字节数,出错返回-1,错误信息存放在errno中。参数:与read函数参数具有相同意义。在本文中,write函数的使用是在爬虫向服务器发送请求这一环节,这里顺便了解一下请求的具体内容,详见以下代码(摘自http.cpp):string Uagent = UAGENT, Conn = CONN, Accept = ACCEPT;string request = "GET /"+ url_t.GetFile() + " HTTP/1.1rnHost: "+ url_t.GetHost() + "rnUser-Agent: &

52、quot; + Uagent + "rnAccept: " + Accept + "rnConnection: " + Conn + "rnrn" int d, total = request.length(), send = 0;while(send < total) if(d = write(sockfd, request.c_str()+send, total-send) < 0) return -1;send += d;其中的宏定义如下(摘自http.h):#define UAGENT "Wget/1.1

53、0.2"#define ACCEPT "*/*"#define CONN "keep-alive"其中request的请求内容是有一定格式限制的,开头必须是“GET /” + 要抓取的网页路径 + HTTP协议 + 主机名 + 等,有些选项是可选的。其中的Uagent也可以不指定,虽然不推荐这样做。因为网站开发人员若不希望一些爬虫来访问他的网页,他们可以在robot.txt中添加限制某些爬虫不允许访问的条件;但这样问题又来了,使用爬虫的人希望抓取更多的网页,因此不希望被服务器拒绝。这样的矛盾一直存在,只不过从道德层面上来讲,还是加上用户代理这个

54、选项。常见的用户代理(User Agent)有Mozilla/4.0,Opera/9.80等。其中需要注意格式的要求,比如空格,回车换行等,最后四个字符(两个回车,两个换行)表示命令的结束。(4)close() 函数该函数用来关闭套接字,并终止TCP连接。函数原型:#include <unistd.h>int close(int sockfd);参数:sockfd为socket函数返回的套接字描述符。返回:成功返回0,反之返回-1。(5)其它重要函数前文提到了gethostbyname函数,它通过传入hostname来返回主机名,结果指向一个struct hostent类型的结构体

55、。函数原型:#include <netdb.h>struct hostent *gethostbyname(const char *hostname);参数:hostname为用户指定的域名。返回:成功返回非空指针,反之则为NULL。/ 例子(摘自http.cpp)if(Host = gethostbyname(hname.c_str() = NULL) return -1;在文本使用的爬虫中,gethostbyname函数只需调用一次,因为本文前提是在同一域名下抓取网页。当然如果抓取范围没有限制,则需对不同域名的网站多次调用该函数。/ SetNoblocking函数(摘自http

56、.cpp)int SetNoblocking(const int& sockfd) int opts = fcntl(sockfd, F_GETFL);/ get file_flag and access modelif (opts < 0) return -1;opts |= O_NONBLOCK;/ set nonblockingif (fcntl(sockfd, F_SETFL, opts) < 0) return -1;SetNonblocking函数不是系统函数,本文把它单独提出来是因为它是实现非阻塞读写、connect等操作的开关。4.2.6 EPOLL模型及其使用(1)EPOLL模型介绍在Linux网络编程中,大家常用的是多路复用IO接口select/poll来触发事件,在这里介绍它的增强版epoll。与select/poll相比,epoll最大的好处是不会随着fd的增加而降低效率,因为select/poll是通过轮询来处理事件的,因此会随着fd 的增加效率降低。在epoll中,首先需要了解的有三个函数:int epoll_create(int size);该函数用来创建一个epoll的文件描述符。参数 size:能够最大监听的socket

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论