当前位置: 首页 > 科技观察

教你使用Scrapy框架爬取北京新发地行情(理论)

时间:2023-03-17 17:40:50 科技观察

大家好!我是林英雄。上个月写了一篇关于IP代理的文章,教大家用XPath爬取免费代理IP。今天分享我的第二篇文章,希望大家喜欢。前言一天,逛街时,突然被一位“美男”打断。回头一看,原来是水果摊阿姨叫我去买水果。她说我长得真漂亮,就以便宜的价格给我买了。我无法拒绝,因为我很自恋。阿姨说我长得漂亮,就买了很多水果回家了。家人问我水果多少钱,结果说是的,水果很贵!今天我们利用scrapy框架爬取北京新发地物价市场,了解商品价格,家人再也不怕我买贵的东西了。Scrapy简介在爬取之前,我们先了解一下Scrapy框架是什么。Scrapy是一个基于Twisted的异步处理框架。它是一个用纯Python实现的爬虫框架。它是为提取结构化数据而编写的应用程序框架。结构清晰,模块间耦合度低,可扩展性强。我们只需要少量的代码就可以快速的抓取数据。Scrapy框架介绍首先我们来看一下经典的Scrapy框架图,如下图所示:学习Scrapy框架的人大部分都看过这张图,分为很多部分。接下来,我们简单的通过下表来了解各个部分的作用。名称功能你想手写代码吗?Engine负责不同模块之间数据和信号的传输。NoScheduler调度器,存储引擎发送的请求,当引擎再次请求时,将请求提供给引擎。NoDownloaderDownloader,下载网页响应的内容,并将内容返回给引擎。NoSpiders爬虫,对引擎传过来的网页内容进行处理,提取数据和url,返回给引擎。它是ItemPipeline管道,负责处理引擎传递过来的数据,其主要任务是对数据进行清洗、校验和存储。它是DownloaderMiddlewares,引擎和下载器之间的桥梁框架,主要处理引擎和下载器之间的请求和响应,可以自定义下载扩展,比如设置代理。一般不需要写SpiderMiddlewaresSpider中间件,引擎和爬虫之间的桥梁框架,主要处理对爬虫的输入响应和输出结果以及新的请求。在表格中我们可以发现每个部分都要经过引擎,上图中的ScrapyEngine部分也被放在了中间。可见Engine引擎是整个框架的核心。注意:这些模块只有Spiders和ItemPipeline需要我们自己手写代码,其他大部分不需要。Scrapy项目对Scrapy框架的各个部分有了大致的了解之后,接下来我们开始创建Scrapy项目。我们可以使用如下命令:scrapystartproject创建一个名为test1的scrapy项目,如下图:这样我们就可以创建Scrapy项目了,如下图:其中:spiders:存放蜘蛛的文件夹;items.py:Items的定义,定义了要爬取的数据结构;middlewares.py:项目中间件文件,定义了爬虫中间件;pipelines.py:项目管道文件,定义数据管道;settings:项目设置文件;scrapy.cfg:Scrapy部署配置文件。蜘蛛爬虫创建蜘蛛爬虫要创建蜘蛛爬虫,首先我们需要进入刚刚创建的Scrapy目录,然后在命令行中运行以下命令:scrapygenspider<爬虫名称><允许爬取的域名>withhttp://quotes.toscrape。com网站为例,该网站是一个著名作家的著名网站,创建一个蜘蛛爬虫如下图所示:创建一个蜘蛛爬虫后,在spiders文件夹下有一个firstspider.py,这个py文件就是我们的爬虫创建完成,文件内容如下所示:importscrapyclassFirstspiderSpider(scrapy.Spider):name='firstSpider'allowed_domains=['quotes.toscrape.com']start_urls=['http://quotes.toscrape.com/']defparse(self,response):pass其中:classFirstspiderSpider()是一个自定义的蜘蛛类,继承自scrapy。Spidername是一个字符串,定义了这个爬虫的名字,每个项目唯一的名字,用来区分不同的蜘蛛,启动爬虫名称时使用scrapycrawl+thecrawler;allowed_domains是允许爬取的域名,防止爬虫爬到其他网站;start_urls是开始抓取的url;parse()方法负责解析返回的响应、提取数据或进一步生成要处理的请求。注意:不能修改该方法的名称。parse()提取数据并启动爬虫在大致了解了firstspider.py文件的内容之后,我们接下来尝试在parse()方法中提取响应数据。具体代码如下:xpath_parse=response.xpath('/html/body/div[1]/div[2]/div[1]/div')forxpathinxpath_parse:item={}item['text']=xpath.xpath('./span[1]/text()').extract_first().replace('"','').replace('"','')item['author']=xpath.xpath('./span[2]/small/text()').extract_first()print(item)这样我们就成功提取了引擎响应的内容数据,接下来输入如下命令运行蜘蛛爬虫:scrapycrawlfirstSpider运行结果如下:运行后发现有我们的结果中有很多日志。这时候,我们可以通过在settings.py中添加如下代码来屏蔽这些log日志:LOG_LEVEL="WARNING"这样我们就可以直接输入我们想要的内容了,如下图:有人可能会问:在哪里用户代理集?我们可以在settings.py中设置User-Agent,代码如下:items.py介绍为了避免拼写错误或者定义字段错误,我们可以在items.py文件中定义字段。在上面的数据提取中,我们得到了text、author内容,所以我们可以在items.py中定义text和author字段,具体代码如下:importscrapyclassTest1Item(scrapy.Item):text=scrapy.Field()author=scrapy.Field()在items.py文件中,我们只需要用scrapy.Field()来定义,scrapy.Field()就是一个字典,一般我们可以把这个类理解为一个字典。然后在firstspider.py文件中导入我们的items.py,修改item={},如下图:fromtest1.itemsimportTest1Itemitem=Test1Item()有人可能会说为什么要一举定义字典?当我们拿到数据的时候,使用不同的item来存储不同的数据,当数据交给pipeline时,可以使用isinstance(item,Test1Item)来判断数据属于哪个item,进行不同的data(item)处理。比如我们在获取京东、淘宝、拼多多的数据时,可以在items.py文件中定义相应的字段。具体代码如下:(scrapy.Item):text=scrapy.Field()author=scrapy.Field()定义好字段后,这个我们在pipeline.py文件中写代码,区分不同的item数据。具体代码如下:fromtest1.itemsimportjingdongItemclassTest1Pipeline:defprocess_item(self,item,spider):ifisinstance(item,jingdongItem):print(item)首先我们导入我们的items.py,通过isinstance()函数。pipelines.py引入ItemPipeline作为项目管道。当一个Item生成时,它会被自动发送到ItemPipeline进行处理。我们经常使用ItemPipeline来做以下操作:清理HTML数据;验证爬取的数据并检测爬取的字段;查看并丢弃重复的内容;将抓取结果保存到数据库。pipelines.py的内容如下:fromitemadapterimportItemAdapterclassTest1Pipeline:defprocess_item(self,item,spider):returnitemprocess_item()方法中传入两个参数,一个参数是item,会传入Spider生成的Item每次都作为参数。另一个参数是spider,它是Spider的一个例子。完成流水线代码后,需要在setting.py中开启。启用它的方法非常简单。只需在setting.py的内容中取消注释以下代码即可:ITEM_PIPELINES={'test1.pipelines.Test1Pipeline':300,}其中:test1.pipelines.Test1Pipeline为pipeline的位置;300是管道的重量。注意:管道的权重越小,优先级越高;管道中process_item()方法的名称不能更改为其他名称;可以定义多个管道。当我们有多个蜘蛛爬虫时,为了满足不同蜘蛛爬虫的需求,我们可以定义不同的管道来处理不同的item内容;当一个蜘蛛的内容可能会受到不同的操作,比如存储在不同的数据库中,那么你可以定义不同的管道来处理不同的项目操作。例如,当我们有多个蜘蛛爬虫时,我们可以通过pipeline.py编写代码来定义多个管道,具体代码如下:print(item)returnitemclasstaobaoPipeline:defprocess_item(self,item,spider):ifspider.name=="taobao":print(item)returnitem这样我们就可以处理对应蜘蛛爬虫传过来的数据了。定义好pipeline后,我们需要在settings.py中设置pipeline权重,即pipeline优先运行,具体代码如下:ITEM_PIPELINES={'test1.pipelines.jingdongPipeline':300,'test1.pipelines.taobaoPipeline':301,}数据传输到管道上面我们提取了需要的数据,然后将数据传输到管道,传输很简单,我们只需要使用yield,代码如下:yielditem是正确的,在蜘蛛爬虫中只需要写这行代码就够了,何必用yield呢?我不能使用退货吗?是的,但是yield就是让整个函数成为一个generator,每次遍历的时候都一个一个的读入内存,这样就不会造成内存占用突然增加。我们已经成功获取了一页数据实现翻页,那么问题来了,如何实现翻页,方法有很多,我们主要介绍两种。第一种方法:使用start_requests()方法。我们在蜘蛛爬虫中添加如下代码,也就是我们创建的firstspider.py。具体代码如下:defstart_requests(self):foriinrange(1,3):url=f'https://quotes.toscrape.com/page/{i}/'yieldscrapy.Request(url=url,callback=self.parse)第二种:在parse()方法中,我们可以通过parse()方法实现翻页,实现翻页,具体代码如下:foriinrange(2,3):url=f'https://quotes.toscrape.com/page/{i}/'yieldscrapy.Request(url=url,callback=self.parse)可以发现上面两种翻页方式类似,只是其中一种实现在start_requests()方法,另一个在parse()方法中实现。但是必须使用scrapy.Request()方法,它可以构建请求并指定回调函数scrapy.Requeset(url,callback,method='GET',headers,cookies,meta,dont_filter=False)来提取数据。:url:表示要抓取的url链接;callback:指定传入的url交给哪个解析函数处理;headers:请求头;cookies:存储在用户本地终端的数据,用于识别用户身份和进行会话跟踪;meta:实现在不同的解析函数中传递数据;dont_filter:让scrapy去重不过滤当前url,scrapy默认有url去重功能。保存数据我们已经获取到数据并实现了翻页,接下来就是保存数据了。保存在文件中当我们要将数据保存为文件时,不需要额外的代码,执行如下代码即可:scrapycrawlspider爬虫名-oxxx.json#saveasJSONfilescrapycrawlspider爬虫名-oxxx.jl或者jsonlines#每个Item输出一行jsonscrapycrawlspider爬虫名-oxxx.csv#另存为csv文件scrapycrawlspider爬虫名-oxxx.xml#另存为xml文件想把文件存成什么格式,修改后缀即可。这里我就不一一举例了。在MongoDB中保存当我们要在MongoDB数据库中保存数据时,需要用到ItemPipeline模块,也就是说需要在pipeline.py中编写代码。具体代码如下:frompymongoimportMongoClientclient=MongoClient()collection=client["test1"]["firstspider"]classTest1Pipeline:defprocess_item(self,item,spider):collection.insert(item)returnitem首先我们导入MongoClient模块和实例化MongoClient,创建一个集合,然后在process_item()方法中使用insert()方法向MongoDB数据库中插入数据。好了,这就是所有关于Scrapy的知识。下篇文章,小编将带大家爬取北京新发地的房价行情,顺便巩固一下今天所学的知识。总结大家好,我是林英雄。本文主要分享Scrapy框架的规章制度。Scrapy是一个基于Twisted的异步处理框架。它是一个用纯Python实现的爬虫框架。它是为提取结构化数据而编写的应用程序框架。耦合度低,可扩展性极强。本文转载自微信公众号《Python爬虫与数据挖掘》,可通过以下二维码关注。转载本文请联系Python爬虫与数据挖掘公众号。