《Python程序设计基础》 课件第9章实战项目之 Scrapy 框架_第1页
《Python程序设计基础》 课件第9章实战项目之 Scrapy 框架_第2页
《Python程序设计基础》 课件第9章实战项目之 Scrapy 框架_第3页
《Python程序设计基础》 课件第9章实战项目之 Scrapy 框架_第4页
《Python程序设计基础》 课件第9章实战项目之 Scrapy 框架_第5页
已阅读5页,还剩79页未读 继续免费阅读

下载本文档

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

文档简介

第9章

实战项目之Scrapy框架创建Scrapy工程网页内容解析Items和Spider组件Pipeline组件目录网页内容解析9.29.1创建Scrapy工程9.3Items和Spider组件Pipeline组件9.4知识架构创建Scrapy工程1Scrapy安装与配置2创建Scrapy工程3Scrapy实践经验4学生实践练习知识架构网页内容解析1常用网页解析工具介绍3使用XPath表达式解析网页5学生实践练习4使用CSS表达式解析网页2Scrapy选择器知识架构Items和Spider组件1Items组件2Spider组3学生实践练习知识架构Pipeline组件3Spider中间件4学生实践练习Pipeline组件介绍12下载器中间件9.1创建Scrapy工程1

Scrapy安装与配置

需要单击“File”→“Setting”菜单打开设置界面。在设置界面下左侧选择“Project:工程名称”菜单下的“ProjectInterpreter”选项。在该界面搜索框中搜索“scrapy”,然后单击“InstallPackage”按钮进行安装。安装成功后出现绿色框并在框中提示“Package‘Scrapy’installedsuccessfully”。1.使用PyCharm工具安装9.1创建Scrapy工程1

Scrapy安装与配置

需要将Python安装目录下的Scripts目录,添加到Path环境变量中,打开命令行工具,执行“pipinstallscrapy”命令。2.通过pip命令安装9.1创建Scrapy工程2

创建Scrapy工程

使用命令创建,需要将Python安装目录下的Scripts目录添加到Path环境变量中。在Windows系统中搜索“cmd”,将搜索出命令提示符工具。打开该命令行工具,通过“cd目录”进入新建工程的所在目录,然后使用“scrapystartprojectmovie”创建Scrapy工程。以豆瓣网上影视板块中爬取某部电影名称和评分为例(1)使用命令创建Scrapy项目工程9.1创建Scrapy工程2

创建Scrapy工程

工程中包含的文件介绍如下。①scrapy.cfg:项目的配置文件。②movie/:该项目的Python模块,之后将在此加入代码。③movie/items.py:项目中的Item文件。④movie/pipelines.py:项目中的pipelines文件。⑤movie/settings.py:项目的设置文件。⑥movie/spiders/:放置Spider代码的目录

以豆瓣网上影视板块中爬取某部电影名称和评分为例(2)工程目录结构介绍9.1创建Scrapy工程2

创建Scrapy工程

importscrapy#定义MovieItem类继承Scrapy模块下的Item类classMovieItem(scrapy.Item):name=scrapy.Field()#电影名称score=scrapy.Field()#评分

以豆瓣网上影视板块中爬取某部电影名称和评分为例(3)编写项目中的Item文件,在movie/items.py文件中编写如下代码9.1创建Scrapy工程

2

创建Scrapy工程

importscrapyfrommovie.itemsimportMovieItem#导入items.py文件中的MovieItem类fromscrapy.selectorimportSelector#导入选择器类classMovieSpider(scrapy.Spider):name="movieSpider"#对应爬虫的名称,工程运行时使用

allowed_domains=[""]#允许通过的域名

以豆瓣网上影视板块中爬取某部电影名称和评分为例

(4)在movie工程的“movie/spiders/”目录下,新建movieSpider.py文件,在该文件中编写如下代码9.1创建Scrapy工程2

创建Scrapy工程

#开始爬取的URL地址start_urls=['/subject/26826398/?from=showing']defparse(self,response):#请求到网页内容后调用的方法sel=Selector(response)#创建选择器对象#获取h1标签下span标签中property属性包含itemreviewed内容的标签,并获取其文本name=sel.xpath("//h1/span[contains(@property,'itemreviewed')]/text()").extract()[0]score=sel.xpath("//strong[@class='llrating_num']/text()").extract()[0]print("内容解析后,电影名称为%s,评分为%s"%(name,score))#将MovieItem对象提交到Pipeline处理yieldMovieItem(name=name,score=score)

以豆瓣网上影视板块中爬取某部电影名称和评分为例9.1创建Scrapy工程2

创建Scrapy工程

fromscrapy.exceptionsimportDropItem#电影的处理类,可以将数据保存到数据库或文件中classMoviePipeline(object):defprocess_item(self,item,spider):if"name"initemand"score"initem:#判断数据是否完整#...存储item中的数据print("处理后,电影名称为%s,评分为%s"%(item["name"],item["score"]))returnitemelse:raiseDropItem("item数据不完整%s"%(item))#丢弃该电影数据

以豆瓣网上影视板块中爬取某部电影名称和评分为例

(5)处理Spider组件解析后的内容,在movie/pipelines.py文件中编写如下代码:9.1创建Scrapy工程2

创建Scrapy工程

ITEM_PIPELINES={'movie.pipelines.MoviePipeline':300,}USER_AGENT="Mozilla/4.0(compatible;MSIE6.0;WindowsNT5.1;SV1;AcooBrowser;.NETCLR1.1.4322;.NETCLR2.0.50727)"以豆瓣网上影视板块中爬取某部电影名称和评分为例

(6)配置浏览器的Agent及Pipeline组件,在movie/settings.py文件中添加如下配置:9.1创建Scrapy工程2

创建Scrapy工程

importscrapyfromscrapy.crawlerimportCrawlerProcessfromjectimportget_project_settingsfrommovie.spiders.movieSpiderimportMovieSpiderprocess=CrawlerProcess(get_project_settings())process.crawl(MovieSpider)#爬取电影数据process.start()

(7)运行Scrapy工程。Scrapy工程运行有多种方式,常用的两种方式如下:●使用“scrapycrawl爬虫名称”命令。●创建Python程序运行(推荐使用)。使用该方式可以通过断电调试Scrapy工程中的Python程序。需要在工程movie的根目录下新建run.py文件,该文件的代码如下:9.1创建Scrapy工程2

创建Scrapy工程

以豆瓣网上影视板块中爬取某部电影名称和评分为例

通过运行该文件也可以实现运行Scrapy项目,豆瓣电影爬取的运行结果如图9.1创建Scrapy工程3Scrapy实践经验

1.分布式爬虫

在批量爬取大量的数据时,消耗的CPU、内存资源比较多,一台服务器的性能有限,购买超级计算机的成本又很高。因此可以使用多台服务器一起爬取数据。这种方式称为分布式爬虫。Scrapy并没有提供内置的机制支持分布式爬取。分布负载最简单的办法就是在不同的机器上安装爬虫程序,将爬虫内容分为多个部分,每台机器上负责爬取的内容都不一样。

在热词分词平台中,新闻包含很多类目,如国内新闻、财经和国际新闻等。如果想要在多个机器上运行一个单独的Spider,可以在每个机器上负责不同类目的处理。9.1创建Scrapy工程3Scrapy实践经验

2.避免被禁止(ban)

有些网站实现了特定的机制,使用一定规则来避免被爬虫爬取。与这些规则打交道并不容易,需要技巧。处理站点的建议如下:(1)使用UserAgent池,如下载器中间件中讲到的UserAgent切换,轮流选择其中的一个作为UserAgent,池中包含常见的浏览器的UserAgent。(2)禁止Cookies,Cookies是指某些站点为了辨别用户身份而储存在用户本地终端(ClientSide)上的数据(通常经过加密)。禁止Cookies也就防止了可能使用Cookies识别爬虫轨迹的站点。(3)设置下载延迟,主要是设置下载的等待时间,大规模集中的访问对Server的影响最大,相当于短时间中增大Server负载。下载等待时间长,不能满足短时间大规模抓取的要求,太短则大大增加被禁止的概率。(4)使用IP地址池(Torproject、VPN和代理IP),其中,Torproject是免费的,具体请搜索Torproject。(5)使用高度分布式的下载器(Downloader)来绕过禁止(Ban),它只需要专注分析处理页面。9.1创建Scrapy工程3Scrapy实践经验

3.Scrapy配置

常用的Scrapy配置有以下7点。1)增加并发2)降低log级别3)禁止重试4)减少下载超时5)禁止重定向6)Robots协议7)配置请求头9.1创建Scrapy工程4学生实践练习

1.需求说明

熟悉Scrapy的工程结构。使用Scrapy框架爬取手机版网易(3)上某个新闻的内容,链接为“http://3/all/article/CS2F8U6N00018AOQ.html#offset=0”的这条新闻。2.实现思路(1)安装和配置Scrapy库,使用命令创建Scrapy工程,使用命令行工具执行“scrapystartprojectmynews”命令,创建MyNews工程。(2)在mynews/items.py文件中新建NewItem,该类包含新闻标题和新闻内容两个字段。(3)在MyNews工程的mynews/spiders/目录下,新建newsSpider.py文件,实现新闻的爬取。(4)在mynews/pipelines.py文件中处理Spider组件解析后的内容,输出新闻的内容。(5)在mynews/settings.py文件中,添加agent设置及Pipeline组件。(6)在工程目录下创建run.py,执行该文件从而实现工程的运行。知识架构网页内容解析1常用网页解析工具介绍3使用XPath表达式解析网页5学生实践练习4使用CSS表达式解析网页2Scrapy选择器9.2网页内容解析1

常用网页解析工具介绍

Spider组件主要用来爬取网页的内容,但如果要获取需要的数据,还需要解析网页中的内容。解析网页内容的字符串方式有许多,比较基础的可以使用字符串本身提供的特性和方法解析。也可以使用正则表达式解析,但正则表达式使用相对较难,学习成本较高,因此一般情况下不建议使用。

除了上述两种方式,第三方库也可以解析网页内容,常见的方式如下:(1)BeautifulSoup是在程序员间非常流行的网页分析库,它基于HTML代码的结构,来构造一个Python对象,对不良标记的处理也非常合理,但它的缺点是执行效率比较低。(2)lxml是一个基于ElementTree(不是Python标准库的一部分)的Python化的XML解析库(也可以解析HTML)。9.2网页内容解析2Scrapy选择器

Scrapy选择器是以文字(Text)或TextResponse构造Selector为实例的。其根据输入的类型自动选择最优的分析方法(XML或者HTML类型)。Scrapy选择器语法如下。

第一种方式如下:fromscrapy.selectorimportSelector选择器对象名=Selector(text=网页内容字符串)选择器对象名.xpath('XPath表达式').extract()第二种方式如下:fromscrapy.httpimportHtmlResponse#创建HtmlResponse对象,其中URL参数主要用来判断URL是否可以访问response=HtmlResponse(url='',body=网页内容字符串)Selector(response=response).xpath('XPath表达式').extract()9.2网页内容解析2

Scrapy选择器

示例9.1使用Scrapy选择器获取一段HTML内容中某个标签的内容#第一种方式fromscrapy.selectorimportSelectorhtml='<html><body><span>good</span></body></html>'spanText=Selector(text=html).xpath('//span/text()').extract()print(spanText)#第二种方式fromscrapy.httpimportHtmlResponseresponse=HtmlResponse(url='',body=html,encoding="utf-8")spanText=Selector(response=response).xpath('//span/text()').extract()print(spanText)9.2网页内容解析2Scrapy选择器

示例9.1的运行结果如图9.2网页内容解析3

使用XPath表达式解析网页

XPath表达式中符号的含义见表,示例中解析的内容如下:<html><body><span>good</span></body></html>'9.2网页内容解析3

使用XPath表达式解析网页

XPath提供了text()方法获取标签中的内容,使用“@href”标记获取标签的href属性,使用[contains(@href,"image")]获取标签href属性中是否包含image内容的标签,这三种表达式使用的示例如下:

//title/text():选择title标签内的文字

//a/@href:选择a标签的href属性

//a[contains(@href,"image")]/@href:选择a标签中href属性值包含image的标签,再获取它的href属性XPath还可以使用正则表达式匹配查询相应的标签。//li[re:test(@class,"item-\d$")]/@href:表示获取所有li标签中class属性值,满足正则表达式"item-\d$"的标签再获取它的href属性9.2网页内容解析3

使用XPath表达式解析网页

使用选择器的xpath()方法解析网页中的内容,在网页内容中解析出产品名称、存储空间及价格信息。解析的网页内容如下:<html><ahref="/max2"><h1class="J_proName">小米Max2</h1></a><divclass="proContent"><span>64GB</span><ul><liid="totlePrice">1999元</li></ul></div></html>9.2网页内容解析3

使用XPath表达式解析网页

fromscrapy.selectorimportSelectorhtml='''<html><ahref="/max2"><h1class="J_proName">小米Max2</h1></a><divclass="proContent"><span>64GB</span><ul><liid="totlePrice">1999元</li></ul></div></html>'''sel=Selector(text=html)print("产品的链接地址为:",sel.xpath("//a/@href").extract()[0])#查找a标签中href属性包含mi字符串的标签,并获取href属性值print("产品的链接地址为:",sel.xpath("//a[contains(@href,'mi')]/@href").extract()[0])print("产品名称为:",sel.xpath("//h1[@class='J_proName']/text()").extract()[0])print("产品的价格为:",sel.xpath("//li[@id='totlePrice']/text()").extract()[0])print("产品的类型为:",sel.xpath("//div[@class='proContent']/span/text()").extract()[0])示例9.29.2网页内容解析3

使用XPath表达式解析网页

使用选择器的xpath()方法解析网页中的内容,运行结果如图9.2网页内容解析4使用CSS表达式解析网页

选择器处理提供xpath()方法,还提供了css()方法。CSS的表达式与jQuery中的表达式类似(1)*:选择所有标签。(2)a:选择<a>标签。(3).link:选择所有class="link"的元素。(4)a.link:选择class="link"的<a>标签。(5)a#home:选择id="home"的<a>标签。(6)a>span:选择父元素为<a>标签的所有<span>子标签。(7)aspan:选择<a>标签内部的所有<span>标签。(8)a[title=Home]:选择title属性为“Home”的所有<a>标签。(9)a[href*=mi]:查找a标签中href属性包含mi字符串的所有<a>标签(10)#elementId::text:获取id为elementId的标签的文本内容。(11).link::attr(href):获取class为link的标签的href属性值。9.2网页内容解析4使用CSS表达式解析网页

示例9.3fromscrapy.selectorimportSelectorhtml='''<html><ahref="/max2"><h1class="pro-titleJ_proName">小米Max2</h1></a><divclass="proContent"><span>64GB</span><ul><liid="totlePrice">1999元</li></ul></div></html>'''sel=Selector(text=html)print("产品的链接地址为:",sel.css("a::attr(href)").extract()[0])#查找a标签中href属性包含mi字符串的标签,并获取href属性值print("产品的链接地址为:",sel.css("a[href*=mi]::attr(href)").extract()[0])print("产品名称为:",sel.css("h1.J_proName::text").extract()[0])print("产品的价格为:",sel.css("#totlePrice::text").extract()[0])print("产品的类型为:",sel.css("Contentspan::text").extract()[0])9.2网页内容解析4使用CSS表达式解析网页

使用选择器的css()解析网页中的内容,运行结果如图9.2网页内容解析5学生实践练习

1.需求说明

从网易新闻页面中获取新闻的数据。

(1)获取手机版网易新闻上某个新闻的网页内容,如获取“https://3/news/article/EN3JOB50000189FH.html?clickfrom=index2018_news_newslist#offset=0”上的内容(网址具有时效性,可以自由更换)

(2)使用Scrapy选择器解析出新闻的标题、时间和新闻内容。2.实现思路(1)定义一个函数getPageContent(),函数根据请求对象获取网页内容。(2)使用Scrapy选择器中的xpath()方法或css()方法,获取网页中指定的内容。知识架构Items和Spider组件1Items组件2Spider组3学生实践练习9.3Items和Spider组件1

Items组件

在命令行工具中执行“scrapystartprojectproduct”命令,在PyCharm工具中打开该工程,工程结构如图9.11所示。

Items组件对应product工程中的product/items.py文件。爬取的主要目标就是从网页中提取结构性数据。Scrapy提供Item类,用来保存这些结构性数据。其提供了类似于字典的方法、结构及用于声明可用字段的简单语法。Item使用简单的class定义语法和Field对象来声明,使用Items组件语法如下:importscrapy#导入Scrapy模块class类名(scrapy.Item):#定义一个类,该类继承Scrapy下的Item类attr1=scrapy.Field()#属性值都为Field对象attr2=scrapy.Field()9.3Items和Spider组件1

Items组件

示例9.4

定义一个产品的Item类,类名为Product,该类包含name(产品名称)和price(产品价格)两个属性。

在product工程的product/items.py文件中的代码如下:importscrapy#定义Product类,该类继承Scrapy模块下的Item类classProduct(scrapy.Item):name=scrapy.Field()price=scrapy.Field()9.3Items和Spider组件1

Items组件

Items组件的使用与字典的使用很类似,Item类的对象创建除了Python程序中对象创建的方式,还可以通过“对象名=类名(属性名1=属性值1,属性名2=属性值2)”的方式创建。其语法如下:对象名=类名()#创建对象的第一种方式对象名=类名(属性名1=属性值1,属性名2=属性值2)#创建对象的第二种方式并给属性赋值对象名=类名(字典对象)#创建对象的第三种方式9.3Items和Spider组件1

Items组件

对象创建完后,还可以通过“对象名["属性名"]=属性值”的方式给对象中的属性赋值。注意不要使用传统的“对象名.属性名=属性值”的方式赋值。属性赋值后可以通过get函数或者“对象名["属性名"]”语句获取属性值。其语法如下:对象名["属性名"]=属性值#属性赋值变量名=对象名["属性名"]#属性访问的第一种方式变量名=对象名.get("属性名")#属性访问的第二种方式9.3Items和Spider组件1

Items组件

在product工程的product/items.py文件中添加示例9.5中的代码示例9.5if__name__=="__main__":#类似于main函数

pro=Product()#创建Product对象

#给对象的name属性赋值,不能使用="mi7"方式

pro["name"]="mi7"

#判断属性是否被赋值,如果没有,则会抛出“KeyError”异常,如pro["price"]

if'name'inpro:

print("产品名称为:",pro["name"])#获取name属性值

print("产品名称为:",pro.get("name"))#获取name属性值

#创建对象第二种方式

pro2=Product(name="meizupro7",price=2399)

if'name'inpro2:

print("产品名称为:",pro2["name"])#获取name属性值9.3Items和Spider组件1

Items组件

运行items.py文件的结果如图9.3Items和Spider组件2Spider组件

Spider组件放在product工程的product/spiders/目录中,它是网页爬取的核心组件使用Spider组件爬取网页,步骤如下:(1)通过Scrapy模块中Spider类提供的start_requests()方法初始化网页请求对象Request,并设置parse()回调函数。当使用Request对象获取到网页数据时,将生成Response对象,并作为参数传给parse()函数。(2)在回调函数内解析返回的网页内容,返回Item对象、Request或者一个包含两者的可迭代容器。返回的Request对象之后会经过Scrapy处理,下载相应的内容,并调用设置的回调函数(3)在回调函数内,可以使用选择器(Selectors)(也可以使用BeautifulSoup、lxml或者任何解析器)来分析网页内容,并根据解析的数据生成Item对象。9.3Items和Spider组件2Spider组件

使用Spider组件爬取网页,步骤如下:(4)由Spider返回的Item对象将被ItemPipeline处理。在Pipeline中保存Item对象中的数据到数据库中或使用Feedexports存入到文件中。Spider组件需要在Scrapy工程中的“工程名称/spiders/”目录下新建Python文件。其语法如下:importscrapy#定义一个类继承Spider类class类名(scrapy.Spider):

name="Spider组件名称属性"

allowed_domains=["允许通过的域名"]

start_urls=['开始爬取的网页地址属性']

#获取到网页数据后执行

defparse(self,response):

#创建Scrapy的选择器,也可以使用BeautifulSoup,lxml分析网页内容

9.3Items和Spider组件2Spider组件

以爬取小米官网两个产品的内容为例,在product工程中的“product/spiders/”目录下新建productSpider.py文件。示例9.6defparseNext(self,response):#解析下一个产品地址

print("下一个Url地址为",response.url)

yieldself.parseProduct(response)defparseProduct(self,response):#解析获取到的网页内容并返Items对象

sel=Selector(response)

#通过解析器解析产品名称

name=sel.css("#J_proHeaderh2::text").extract()[0]

print("解析后产品名为%s"%(name))

returnProduct(name=name,price="")9.3Items和Spider组件2Spider组件

在工程的product/pipelines.py文件中的代码如下:classProductPipeline(object):

defprocess_item(self,item,spider):

print("需要处理的产品名为%s"%(item["name"]))

returnitem在工程的product/settings.py文件中增加如下配置:

ITEM_PIPELINES={

'product.pipelines.ProductPipeline':300,}

USER_AGENT="Mozilla/4.0(compatible;MSIE6.0;WindowsNT5.1;SV1;AcooBrowser;.NETCLR1.1.4322;.NETCLR2.0.50727)"9.3Items和Spider组件2Spider组件

在工程目录下新建run.py文件,通过执行该文件运行Scrapy工程,代码如下:

importscrapy

fromscrapy.crawlerimportCrawlerProcess

fromjectimportget_project_settings

fromductSpiderimportProductSpider

process=CrawlerProcess(get_project_settings())

process.crawl(ProductSpider)

process.start()9.3Items和Spider组件2Spider组件

执行run.py文件后,运行结果如图9.3Items和Spider组件3Spider组件

使用Scrapy框架爬取手机版网易新闻列表。1.需求说明2.实现思路(1)使用“scrapystartprojectnews163”命令创建名称为“news163”的工程。(2)在PyCharm工具中打开该工程。(3)编写工程的Items组件,类中包括title、news_time、content、url和docid(新闻编号)这5个字段。(4)在工程的“news163/spiders”目录下创建newSpider.py文件,用来爬取新闻数据。(5)在工程的news163目录下的pipelines.py文件中处理新闻数据,仅输出新闻数据即可。(6)在settings.py文件中添加Pipelines及Use-Agent配置,并在工程下新建run.py文件运行该工程.知识架构Pipeline组件3Spider中间件4学生实践练习Pipeline组件介绍12下载器中间件9.4Pipeline组件1

Pipeline组件介绍

在命令行工具中执行“scrapystartprojectnews”命令,创建新工程,Pipeline组件对应news工程中的news/pipelines.py文件。当Item在Spider中被收集之后,它将会被传递到ItemPipeline,在Pipeline中对Item中的数据进行处理。Pipeline组件对Item典型的处理有以下几种方式:(1)清理HTML数据。(2)验证爬取的数据,检查Item包含某些字段。(3)查重并丢弃。(4)将爬取结果保存到数据库中。9.4Pipeline组件1

Pipeline组件介绍

编写Pipeline比较简单,每个Pipeline组件是一个独立的Python类,该类必须实现process_item(self,item,spider)方法。其中参数item表示被爬取的Item对象,spider表示爬取该Item对象的Spider对象。每个Pipeline都会调用该方法。该方法必须返回一个Item对象。如果想放弃该Item对象,可以抛出DropItem异常。放弃后将不会被之后的Pipeline组件所处理。此外,Pipeline组件也可以实现以下方法:(1)open_spider(self,spider):当Spider被开启时调用,Spider表示被开启的Spider。(2)close_spider(self,spider):当Spider被关闭时调用,Spider表示被关闭的Spider。9.4Pipeline组件1

Pipeline组件介绍

示例9.7fromscrapy.exceptionsimportDropItemclassProductPipeline(object):

def__init__(self):#构造方法,用来初始化数据

pass

defprocess_item(self,item,spider):

if"name"initem:#判断item中是否有name属性值

print("产品名称为:",item["name"])

print("产品价格为:",item["price"])

returnitem#必须返回item对象或抛出DropItem异常

else:

raiseDropItem("无效的Item数据:%s"%item)

创建一个产品数据爬取Scrapy项目的Pipeline组件。如果Item组件中没有产品名称,就放弃该Item组件,如果存在就输出到控制台。在news工程中的news/pipelines.py文件中添加代码,详细代码见示例9.4Pipeline组件1

Pipeline组件介绍

classDuplicatesPipeline(object):#去除重复的记录

def__init__(self):#构造方法,用来初始化数据

self.idSet=set()#定义idset属性保存所有的id集合

defprocess_item(self,item,spider):

ifitem['id']inself.idSet:#判断item中的id属性是否已经存在

raiseDropItem("重复的item数据:%s"%item)

else:

self.idSet.add(item['id'])

returnitem

很多时候我们会重复爬取某些网页数据,最终导致Pipeline组件处理过程中遇到重复的Item对象,但必须保证数据库中存储的记录是唯一的,所以需要在Pipeline组件中去除重复的记录,在news工程中的news/pipelines.py文件中继续添加如下代码:9.4Pipeline组件1

Pipeline组件介绍

ITEM_PIPELINES={

'news.pipelines.DuplicatesPipeline':300,

'news.pipelines.ProductPipeline':500,

}

在上文中,介绍了Pipeline的作用及创建,但并没有启动Pipeline组件。为了启用一个ItemPipeline组件,必须将它的类添加到settings.py文件的ITEM_PIPELINES配置中,

以下是对ProductPipeline类和DuplicatesPipeline类的配置:9.4Pipeline组件2

下载器中间件

1.下载器中间件介绍

下载器中间件是处于Scrapy的Request请求和Response响应之间的一个组件,用于修改全局的Request和Response,可以帮助定制自己的爬虫系统。2.编写下载器中间件1)process_request(request,spider)方法

(1)方法说明。当每个Request通过下载中间件时,该方法被调用。必须返回None、Response对象和Request对象中的一个或者通过“raiseIgnoreRequest”语句产生一个IgnoreRequest异常。

(2)参数。

request(Request对象):处理的Request。

Spider(Spider对象):该Request对象对应的Spider。9.4Pipeline组件2

下载器中间件

(3)返回值。

如果返回None,Scrapy将继续处理该Request,执行其他中间件的相应方法,直到Request被执行(其Response被下载)。

如果返回Response对象,Scrapy将不会调用任何其他的process_request()方法或process_exception()方法,或相应地下载函数;其将返回该Response。

如果返回Request对象,Scrapy则停止调用process_request方法并重新调度返回的Request。当新返回的Request被执行后,对应的中间件将会根据下载的Response被调用。

如果产生一个IgnoreRequest异常,则安装的下载中间件process_exception()方法会被调用。如果没有任何一个方法处理该异常,则Request的errback(Request.errback)方法会被调用。如果没有代码处理抛出的异常,则该异常被忽略且不记录。2.编写下载器中间件9.4Pipeline组件2

下载器中间件

2)process_response(request,response,spider)方法

(1)方法说明。该方法主要用来处理产生的Response,返回值必须是Reponse对象、Request对象中的一个或通过“raiseIgnoreRequest”语句产生一个IgnoreRequest异常。

(2)参数。

request(Request对象):Response对应的Request。

response(Response对象):处理的Response。

spider(Spider对象):Response对应的Spider。2.编写下载器中间件9.4Pipeline组件2

下载器中间件

2.编写下载器中间件

(3)返回值。

如果返回Response对象,可以与传入的Response相同,也可以是新的对象,该Response会被其他中间件的process_response()方法处理。

如果返回Request对象,则中间件停止,返回的Request会被重新调度下载,处理类似于process_request()返回Request。

如果抛出IgnoreRequest异常,则调用Request的errback方法。如果没有代码处理抛出的异常,则该异常被忽略且不记录。9.4Pipeline组件2

下载器中间件

2.编写下载器中间件3)process_exception(request,exception,spider)方法

(1)方法说明。当下载处理器或process_request()抛出异常,如IgnoreRequest异常时,Scrapy调用process_exception(),应该返回None、Request对象或Response对象中的一种。

(2)参数。

request(Request对象):产生异常的Request。

exception(Exception对象):抛出的异常。

spider(Spider对象):Request对应的Spider。9.4Pipeline组件2

下载器中间件

2.编写下载器中间件(3)返回值。

如果返回None,Scrapy将会继续处理该异常,接着调用已安装的其他中间件的process_exception()方法,直到所有中间件被调用完毕,则调用默认的异常处理。

如果返回Reponse对象,则已安装的中间件的process_response()方法被调用,Scrapy将不会调用任何其他中间件的process_exception()方法。

如果返回Request对象,则返回的Request将会被重新调用下载,这将停止中间件的process_exception()方法执行,类似于返回Response对象的处理。

Scrapy代理IP、Uesr-Agent的切换都是通过DOWNLOADER_MIDDLEWARES进行控制的。

Uesr-Agent是指包含浏览器信息、操作系统信息的一个字符串,也称为一种特殊的网络协议。服务器通过它判断当前访问对象是浏览器、邮件客户端还是网络爬虫.9.4Pipeline组件2

下载器中间件

建立User-Agent池实现对User-Agent的切换,在news工程的“news/middlewares.py”文件中添加相关代码。示例9.8importrandomimportbase64#随机使用预定义列表里的User-Agent类classRandomUserAgent(object):

def__init__(self,agents):

#使用初始化的agents列表

self.agents=agents

@classmethod

deffrom_crawler(cls,crawler):

#获取settings的USER_AGENT列表并返回

returncls(crawler.settings.getlist('USER_AGENTS'))

defprocess_request(self,request,spider):

#随机设置Request报/表头header的User-Agent

request.headers.setdefault('User-Agent',random.choice(self.agents))9.4Pipeline组件2

下载器中间件

示例9.8示例9.8还需要在工程的“news/settings.py”文件中添加配置,配置如下:

USER_AGENTS=[

"Mozilla/5.0(compatible;MSIE9.0;WindowsNT6.1;Win64;x64;Trident/5.0;.NETCLR3.5.30729;.NETCLR3.0.30729;.NETCLR2.0.50727;MediaCenterPC6.0)",

"Mozilla/5.0(compatible;MSIE8.0;WindowsNT6.0;Trident/4.0;WOW64;Trident/4.0;SLCC2;.NETCLR2.0.50727;.NETCLR3.5.30729;.NETCLR3.0.30729;.NETCLR1.0.3705;.NETCLR1.1.4322)",

"Mozilla/4.0(compatible;MSIE7.0b;WindowsNT5.2;.NETCLR1.1.4322;.NETCLR2.0.50727;InfoPath.2;.NETCLR3.0.04506.30)",

"Mozilla/5.0(Windows;U;WindowsNT5.1;zh-CN)AppleWebKit/523.15(KHTML,likeGecko,Safari/419.3)Arora/0.3(Change:287c9dfb30)",9.4Pipeline组件2

下载器中间件

示例9.8还需要在工程的“news/settings.py”文件中添加配置,配置如下:示例9.8

"Mozilla/5.0(X11;U;Linux;en-US)AppleWebKit/527+(KHTML,likeGecko,Safari/419.3)Arora/0.6",

"Mozilla/5.0(Windows;U;WindowsNT5.1;en-US;rv:pre)Gecko/20070215K_x0002_Ninja/2.1.1",

"Mozilla/5.0(Windows;U;WindowsNT5.1;zh-CN;rv:1.9)Gecko/20080705Firefox/3.0Kapiko/3.0",

"Mozilla/5.0(X11;Linuxi686;U;)Gecko/20070322Kazehakase/0.4.5"]9.4Pipeline组件2

下载器中间件

在news工程的“news/middlewares.py”文件中,随机使用预定义列表里的Proxy代理。示例9.9#导入settings的PROXIES设置fromsettingsimportPROXIES#随机使用预定义列表里的Proxy代理classProxyMiddleware(object):

defprocess_request(self,request,spider):

#随机获取fromsettingsimportPROXIES里的代理

proxy=random.choice(PROXIES)

#如果代理可用,则使用代理

ifproxy['user_pass']isnotNone:

request.meta['proxy']="http://%s"%proxy['ip_port']

#对代理数据进行base64编码9.4Pipeline组件2

下载器中间件

在news工程的“news/middlewares.py”文件中,随机使用预定义列表里的Proxy代理。示例9.9

encoded_user_pass=base64.encodestring(proxy['user_pass'])

#添加到HTTP代理格式中

request.headers['Proxy-Authorization']='Basic'+

encoded_user_passelse:

print("****代理失效****"+proxy['ip_port'])

request.meta['proxy']="http://%s"%proxy['ip_port']9.4Pipeline组件2

下载器中间件

DOWNLOADER_MIDDLEWARES={

"工程名.middlewares.RandomUserAgent":300,

"工程名.middlewares.ProxyMiddleware":500,

}3.激活下载器中间件

下载器中间件需要在工程的“工程名/settings.py”文件中,增加DOWNLOADER_MIDDLEWARES的配置。该设置是一个字典(Dict),键为中间件类的路径,值为其中间件的顺序(Order),代码如下:9.4Pipeline组件2

下载器中间件

3.激活下载器中间件

该配置将与Scrapy定义的DOWNLOADER_MIDDLEWARES_BASE设置合并,但不是覆盖,而后根据顺序进行排序。由于每个中间件执行不同的动作,中间件可能会依赖于之前(或者之后)执行的中间件,因此顺序是很重要的。

Scrapy定义的DOWNLOADER_MIDDLEWARES_BASE配置如下:9.4Pipeline组件2

下载器中间件

{'scrapy.contrib.downloadermiddleware.robotstxt.RobotsTxtMiddleware':100,'scrapy.contrib.downloadermiddleware.httpauth.HttpAuthMiddleware':300,'scrapy.contrib.downloadermiddleware.downloadtimeout.DownloadTimeoutMiddleware':350,'scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware':400,'scrapy.contrib

温馨提示

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

评论

0/150

提交评论