网络爬虫是捜索引擎抓取系统的重要组成部分。爬虫的主要目的是将互联网上的网页下载到本地形成一个或联网内容的镜像备份。
一、网络爬虫的基本结构及工作流程
一个通用的网络爬虫的框架如图所示:
1.首先选取一部分精心挑选的种子URL;
2.将这些URL放入待抓取URL队列;
3.从待抓取URL队列中取出待抓取在URL,解析DNS,并且得到主机的ip,并将URL对应的网页下载下来,存储进已下载网页库中。此外,将这些URL放进已抓取URL队列。
4.分析已抓取URL队列中的URL,分析其中的其他URL,并且将URL放入待抓取URL队列,从而进入下一个循环。
二、从爬虫的角度对互联网进行划分
1.已下载未过期网页
2.已下载已过期网页:抓取到的网页实际上是互联网内容的一个镜像与备份,互联网是动态变化的,一部分互联网上的内容已经发生了变化,这时,这部分抓取到的网页就已经过期了。
3.待下载网页:也就是待抓取URL队列中的那些页面
4.可知网页:还没有抓取下来,也没有在待抓取URL队列中,但是可以通过对已抓取页面或者待抓取URL对应页面进行分析获取到的URL,认为是可知网页。
5.还有一部分网页,爬虫是无法直接抓取下载的。称为不可知网页。
三、抓取策略
在爬虫系统中,待抓取URL队列是很重要的一部分。待抓取URL队列中的URL以什么样的顺序排列也是一个很重要的问题,因为这涉及到先抓取那个页面,后抓取哪个页面。而决定这些URL排列顺序的方法,叫做抓取策略。
下面重点介绍几种常见的抓取策略
1.深度优先遍历策略:
深度优先遍历策略是指网络爬虫会从起始页开始,一个链接一个链接跟踪下去,处理完这条线路之后再转入下一个起始页,继续跟踪链接。
2.宽度优先遍历策略
宽度优先遍历策略的基本思路是,将新下载网页中发现的链接直接插入待抓取URL队列的末尾。
3.反向链接数策略
反向链接数是指一个网页被其他网页链接指向的数量。反向链接数表示的是一个网页的内容受到其他人的推荐的程度。因此,很多时候搜索引擎的抓取系统会使用这个指标来评价网页的重要程度,从而决定不同网页的抓取先后顺序。
4.Partial PageRank策略
Partial PageRank算法借鉴了PageRank算法的思想:对于已经下载的网页,连同待抓取URL队列中的URL,形成网页集合,计算每个页面的PageRank值,计算完之后,将待抓取URL队列中的URL按照PageRank值的大小排列,并按照该顺序抓取页面。
5.OPIC策略
该算法实际上也是对页面进行一个重要性打分。在算法开始前,给所有页面一个相同的初始现金(cash)。当下载了某个页面P之后,将P的现金分摊给所有从P中分析出的链接,并且将P的现金清空。对于待抓取URL队列中的所有页面按照现金数进行排序。
6.大站优先策略
对于待抓取URL队列中的所有网页,根据所属的网站进行分类。对于待下载页面数多的网站,优先下载。这个策略也因此叫做大站优先策略。
webmagic爬虫框架 (转发自oschaina)
webmagic的目标
一般来说,一个爬虫包括几个部分:
-
页面下载
页面下载是一个爬虫的基础。下载页面之后才能进行其他后续操作。
-
链接提取
一般爬虫都会有一些初始的种子URL,但是这些URL对于爬虫是远远不够的。爬虫在爬页面的时候,需要不断发现新的链接。
-
URL管理
最基础的URL管理,就是对已经爬过的URL和没有爬的URL做区分,防止重复爬取。
-
内容分析和持久化
一般来说,我们最终需要的都不是原始的HTML页面。我们需要对爬到的页面进行分析,转化成结构化的数据,并存储下来。
webmagic的模块划分
webmagic参考了scrapy的模块划分,分为Spider(整个爬虫的调度框架)、Downloader(页面下载)、PageProcessor(链接提取和页面分析)、Scheduler(URL管理)、Pipeline(离线分析和持久化)几部分。
Downloader-页面下载
页面下载是一切爬虫的开始。
大部分爬虫都是通过模拟http请求,接收并分析响应来完成。这方面,JDK自带的HttpURLConnection可以满足最简单的需要,而Apache HttpClient(4.0后整合到HttpCompenent项目中)则是开发复杂爬虫的不二之选。
webmagic使用了HttpClient 4.2,并封装到了
HttpClientDownloader。
下面是一个使用HttpClient最简单的例子:
1.HttpClient httpClient =
new
DefaultHttpClient();
2.
HttpGet httpGet =
new
HttpGet(
"http://youhost/xxx"
);
3.
HttpResponse httpResponse = httpClient.execute(httpGet);
4.
System.out.println(EntityUtils.toString(httpResponse.getEntity().getContent()));
对于一些Javascript动态加载的网页,仅仅使用http模拟下载工具,并不能取到页面的内容。这方面的思路有两种:
一种是抽丝剥茧,分析js的逻辑,再用爬虫去重现它(比如在网页中提取关键数据,再用这些数据去构造Ajax请求,最后直接从响应体获取想要的数据);
另一种就是:内置一个浏览器,直接获取最后加载完的页面。这方面,js可以使用
PhantomJS
,它内部集成了webkit。而Java可以使用
Selenium
,这是一个非常强大的浏览器模拟工具。
PageProcessor-页面分析及链接抽取
这里说的页面分析主要指HTML页面的分析
。页面分析可以说是垂直爬虫最复杂的一部分,在webmagic里,PageProcessor是定制爬虫的核心。通过编写一个实现PageProcessor接口的类,就可以定制一个自己的爬虫。
页面抽取最基本的方式是使用正则表达式。正则表达式好处是非常通用,解析文本的功能也很强大。但是正则表达式最大的问题是,不能真正对HTML进行语法级别的解析,没有办法处理关系到HTML结构的情况(例如处理标签嵌套)。
Java世界主要有几款比较方便的分析工具:
Jsoup
Jsoup是一个集强大和便利于一体的HTML解析工具。它方便的地方是,可以用于支持用jquery中css selector的方式选取元素,这对于熟悉js的开发者来说基本没有学习成本。
HtmlParser
Apache tika
HtmlCleaner与XPath
HtmlCleaner最大的优点是:支持XPath的方式选取元素。XPath是一门在XML中查找信息的语言,也可以用于抽取HTML元素。XPath与CSS Selector大部分功能都是重合的,但是CSS Selector专门针对HTML,写法更简洁,而XPath则是通用的标准,可以精确到属性值。XPath有一定的学习成本,但是对经常需要编写爬虫的人来说,这点投入绝对是值得的。
学习XPath可以参考w3school的XPath 教程。下面是使用HtmlCleaner和xpath进行抽取的一段代码:
1.HtmlCleaner htmlCleaner =
new
HtmlCleaner();
2.TagNode tagNode = htmlCleaner.clean(text);
3.Object[] objects = tagNode.evaluateXPath(
"xpathStr"
);
Scheduler-URL管理
对于小规模的抓取,URL管理是很简单的。
我们只需要将待抓取URL和已抓取URL分开保存,并进行去重即可。使用JDK内置的集合类型Set、List或者Queue都可以满足需要。如果我们要进行多线程抓取,则可以选择线程安全的容器,例如LinkedBlockingQueue以及ConcurrentHashMap。
webmagic目前有两个Scheduler的实现,
QueueScheduler
是一个简单的内存队列,速度较快,并且是线程安全的,
Pipeline-离线处理和持久化
Pipeline其实也是容易被忽略的一部分。大家都知道持久化的重要性,但是很多框架都选择直接在页面抽取的时候将持久化一起完成,例如crawer4j。但是Pipeline真正的好处是,将页面的在线分析和离线处理拆分开来,可以在一些线程里进行下载,另一些线程里进行处理和持久化。