作者: 黄进(QQ:7149101)
一、 网络爬虫
网络爬虫(又被称为网页蜘蛛,网络机器人),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本;它是一个自动提取网页的程序,它为搜索引擎从万维网上下载网页,是搜索引擎的重要组成部分。
网络爬虫分类:
通用网络爬虫
通用网络爬虫又称全网爬虫(Scalable Web Crawler),爬行对象从一些种子 URL 扩充到整个 Web,主要为门户站点搜索引擎和大型 Web 服务提供商采集数据。为提高工作效率,通用网络爬虫会采取一定的爬行策略。常用的爬行策略有:深度优先策略、广度优先策略。
1) 深度优先策略:其基本方法是按照深度由低到高的顺序,依次访问下一级网页链接,直到不能再深入为止。 爬虫在完成一个爬行分支后返回到上一链接节点进一步搜索其它链接。 当所有链接遍历完后,爬行任务结束。 这种策略比较适合垂直搜索或站内搜索, 但爬行页面内容层次较深的站点时会造成资源的巨大浪费;
2) 广度优先策略:此策略按照网页内容目录层次深浅来爬行页面,处于较浅目录层次的页面首先被爬行。 当同一层次中的页面爬行完毕后,爬虫再深入下一层继续爬行。 这种策略能够有效控制页面的爬行深度,避免遇到一个无穷深层分支时无法结束爬行的问题,实现方便,无需存储大量中间节点,不足之处在于需较长时间才能爬行到目录层次较深的页面
聚焦网络爬虫
聚焦网络爬虫(Focused Crawler),又称主题网络爬虫(Topical Crawler),是指选择性地爬行那些与预先定义好的主题相关页面的网络爬虫。
1) 基于内容评价的爬行策略:DeBra将文本相似度的计算方法引入到网络爬虫中,提出了 Fish Search 算法,它将用户输入的查询词作为主题,包含查询词的页面被视为与主题相关,其局限性在于无法评价页面与主题相关度的高低。Herseovic对 Fish Search 算法进行了改进 ,提出了Sharksearch 算法,利用空间向量模型计算页面与主题的相关度大小。
2) 基于链接结构评价的爬行策略 :Web 页面作为一种半结构化文档,包含很多结构信息,可用来评价链接重要性。 PageRank 算法最初用于搜索引擎信息检索中对查询结果进行排序,也可用于评价链接重要性,具体做法就是每次选择 PageRank 值较大页面中的链接来访问。 另一个利用Web结构评价链接价值的方法是 HITS 方法,它通过计算每个已访问页面的 Authority权重和Hub权重,并以此决定链接的访问顺序。
3) 基于增强学习的爬行策略:Rennie 和 McCallum 将增强学习引入聚焦爬虫,利用贝叶斯分类器,根据整个网页文本和链接文本对超链接进行分类,为每个链接计算出重要性,从而决定链接的访问顺序。
4) 基于语境图的爬行策略:Diligenti 等人提出了一种通过建立语境图(Context Graphs)学习网页之间的相关度,训练一个机器学习系统,通过该系统可计算当前页面到相关 Web 页面的距离,距离越近的页面中的链接优先访问。
增量式网络爬虫
增量式网络爬虫(Incremental Web Crawler)是 指 对 已 下 载 网 页 采 取 增 量式更新和只爬行新产生的或者已经发生变化网页的爬虫,它能够在一定程度上保证所爬行的页面是尽可能新的页面。
增量式爬虫有两个目标:保持本地页面集中存储的页面为最新页面和提高本地页面集中页面的质量。 为实现第一个目标,增量式爬虫需要通过重新访问网页来更新本地页面集中页面内容,常用的方法有:1) 统一更新法:爬虫以相同的频率访问所有网页,不考虑网页的改变频率;2) 个体更新法:爬虫根据个体网页的改变频率来重新访问各页面;3) 基于分类的更新法:爬虫根据网页改变频率将其分为更新较快网页子集和更新较慢网页子集两类,然后以不同的频率访问这两类网页。为实现第二个目标,增量式爬虫需要对网页的重要性排序,常用的策略有:广度优先策略、PageRank 优先策略等。
深层网络爬虫
Web 页面按存在方式可以分为表层网页(Surface Web)和深层网页(Deep Web,也称 Invisible Web Pages 或 Hidden Web)。 表层网页是指传统搜索引擎可以索引的页面,以超链接可以到达的静态网页为主构成的 Web 页面。深层网页是那些大部分内容不能通过静态链接获取的、隐藏在搜索表单后的,只有用户提交一些关键词才能获得的 Web 页面。深层网络爬虫体系结构包含六个基本功能模块 (爬行控制器、解析器、表单分析器、表单处理器、响应分析器、LVS 控制器)和两个爬虫内部数据结构(URL 列表、LVS 表)。 其中 LVS(Label Value Set)表示标签/数值集合,用来表示填充表单的数据源。爬取过程中最重要部分就是表单填写,包含两种类型:1) 基于领域知识的表单填写;2)基于网页结构分析的表单填写。
实际的网络爬虫系统通常是几种爬虫技术相结合实现的。
二、 网络爬虫框架Scrapy
网络爬虫框架:
现在比较流行的分布式爬虫,是Apache的Nutch。学习成本高,编写和调试所需的时间较多,抓取速度不是很快;java单机爬虫Crawler4j、WebMagic(支持分布式)、WebCollector,学习成本较低,选择适合业务的爬虫;非java单机爬虫larbin(c++)、scrapy(python),学习成本高,调试耗时较多。
Scrapy的安装
请参考安装向导页面内容进行安装
https://doc.scrapy.org/en/0.16/intro/install.html#intro-install
Scrapy框架(python是基础,目前支持python2.x)
Scrapy的数据处理流程由Scrapy引擎进行控制,其主要的运行方式为:
1. 引擎打开一个域名时蜘蛛处理这个域名,并让蜘蛛获取第一个爬取的URL。
2. 引擎从蜘蛛那获取第一个需要爬取的URL,然后作为请求在调度中进行调度。
3. 引擎从调度那获取接下来进行爬取的页面。
4. 调度将下一个爬取的URL返回给引擎,引擎将他们通过下载中间件发送到下载器。
5. 当网页被下载器下载完成以后,响应内容通过下载中间件被发送到引擎。
6. 引擎收到下载器的响应并将它通过蜘蛛中间件发送到蜘蛛进行处理。
7. 蜘蛛处理响应并返回爬取到的项目,然后给引擎发送新的请求。
8. 引擎将抓取到的项目管道,并向调度发送请求。
9. 系统重复第二部后面的操作,直到调度中没有请求,然后断开引擎与域之间的联系。
各部分的作用
Scrapy Engine(引擎),用来处理整个系统的数据流处理,触发事务;
Spider Middlewares(蜘蛛中间件),介于Scrapy引擎和蜘蛛之间的钩子框架,主要工作是处理蜘蛛的响应输入和请求输出;
Scheduler(Middlewares调度中间件),介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应。
Scheduler(调度器),用来接受引擎发过来的请求,压入队列中,并在引擎再次请求的时候返回;
Downloader Middlewares(下载器中间件),位于Scrapy引擎和下载器之间的钩子框架,主要是处理Scrapy引擎与下载器之间的请求及响应;
Downloader(下载器),用于下载网页内容,并将网页内容返回给蜘蛛;
Spiders(蜘蛛),蜘蛛是主要干活的,用它来制订特定域名或网页的解析规则;
Item Pipeline(项目管道)负责处理有蜘蛛从网页中抽取的项目,他的主要任务是分析、验证和存储数据。当页面被蜘蛛解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
三、Scrapy爬虫实例
1、Scrapy框架中的关键部分描述:
Items:
爬取的主要目标就是从非结构性的数据源提取结构性数据,例如网页。 Scrapy提供Item类来满足这样的需求。Item对象是种简单的容器,保存了爬取到得数据。 其提供了 类似于词典(dictionary-like) 的API以及用于声明可用字段的简单语法。Item使用简单的class定义语法以及 Field 对象来声明。
Spider:
name定义spider名字的字符串(string)。spider的名字定义了Scrapy如何定位(并初始化)spider,所以其必须是唯一的。 不过您可以生成多个相同的spider实例(instance),这没有任何限制。 name是spider最重要的属性,而且是必须的。
allowed_domains可选。包含了spider允许爬取的域名(domain)列表(list)。 当 OffsiteMiddleware 启用时, 域名不在列表中的URL不会被跟进。
start_urls 是URL列表。当没有制定特定的URL时,spider将从该列表中开始进行爬取。 因此,第一个被获取到的页面的URL将是该列表之一。 后续的URL将会从获取到的数据中提取。
parse(response)当response没有指定回调函数时,该方法是Scrapy处理下载的response的默认方法。parse负责处理response并返回处理的数据以及(/或)跟进的URL。 Spider 对其他的Request的回调函数也有相同的要求。
Item Pipeline:
当Item在Spider中被收集之后,它将会被传递到Item Pipeline,一些组件会按照一定的顺序执行对Item的处理。每个item pipeline组件(有时称之为“Item Pipeline”)是实现了简单方法的Python类。他们接收到Item并通过它执行一些行为,同时也决定此Item是否继续通过pipeline,或是被丢弃而不再进行处理。
process_item(self, item, spider)每个item pipeline组件都需要调用该方法,这个方法必须返回一个 Item (或任何继承类)对象,或是抛出 DropItem 异常,被丢弃的item将不会被之后的pipeline组件所处理。
open_spider(self, spider)当spider被开启时,这个方法被调用。
close_spider(spider)当spider被关闭时,这个方法被调用。
2、创建一个爬虫工程
打开命令行,进入要创建项目的目录后,执行 scrapy startproject myCrawl命令,项目创建成功。
3、简单爬虫程序
首先在items.py文件中增加如下内容:
我们定义了item对象来存放抓取到的数据
接下来在spiders目录下创建一个新的文件firstSpider.py
在文件中写入下面代码,我们的爬取程序基本功能就完成了
这个爬虫主要做的事情是将访问页面中//div/ul/li/p下的超链接的文本以及连接URL进行抓取,并将抓取到的值存放在item对象中。
这里讲解一下主要代码:
这里的name是spider最重要的属性,而且是必须的,它定义了我们的爬虫名称;
start_urls这里定义了我们默认要爬取的网页地址列表;
parse是默认的Request对象回调函数,处理返回的response,必须实现这个函数;HtmlXPathSelector这个是将response解析成HTML实例,通过select表示一个xpath参数表达式选择的节点;
extract()返回一个unicode字符串;
接下来我们要做的事情就是将item对象中的的数据保存下来,当然保存方式是灵活选择的可以保存在文件中,也可以保存到数据库表中。这个例子我们用mysql数据库作为存储数据的介质。
如何保存数据?
首先,在pipelines.py文件中加入下面的代码。
from_settings是一个类方法主要是做数据库连接并返回连接池对象;
Twisted 提供了 twisted.enterprise.adbapi, 遵循DB-API 2.0协议的一个异步封装。
runInteraction调用它们的时候会带上一个function,function会在线程中通过 adbapi.Transaction 来执行,数据库事务将在操作完成时进行提交;
addErrback捕获异常信息;写好了MySQLStoreCnblogsPipeline类之后,还需要在settints.py中配置数据库连接参数,以及启用我们新写的MySQLStoreCnblogsPipeline,见下图
到这里我们从页面抓取并保存到数据库的一个爬虫程序就全部完成了。
4、进阶爬虫实例
前面的例子主要是抓取静态页面中的内容,我们日常中的抓取数据是动态加载的,这种情况想要抓取到数据要怎么做??
主要有以下两种方式:
1) 通过对请求数据的url进行拼装,模拟浏览器对网页进行动态加载后得到源代码数据,再进行分析;scrapy+Spynner,scrapy+selenium
2) 通过抓包工具分析js,ajax的请求,模拟该请求获取js加载后的数据;谷歌浏览器开发者工具
第一种方式网上讲的比较多,下面主要对第二种方式进行介绍讲解。
首先,讲一下我的需求,我需要爬取下面网站的数据,但是数据都是动态加载的,在网页源码中没有数据信息;
首先,在items.py中定义存储对象ContentItem,具体定义如下:
在spiders目录新建爬虫文件secondSpider.py,代码如下:
首先通过爬取列表触发框架爬取,然后使用requests的方法直接调用查询数据的url,这样就可以直接拿到返回的数据。通过拿到的数据总数,可以直接通过请求获取到所有数据,这样就省去了翻页等复杂的操作;我们将爬回来的数据存到json文件中,在pipelines.py文件中新增一个pipeline。具体见下面代码:
爬取结果: