Scrapy深入学习pipelines管道文件

鳄鱼君

发表文章数:642

Vieu四代商业主题

高扩展、安全、稳定、响应式布局多功能模板。

¥69 现在购买
首页 » Python » Scrapy深入学习pipelines管道文件

Scrapy深入理解pipelines文件

每个管道组件都是具有某个功能的Python类,常见的功能有:清理html数据,做确认,去重,存入数据。每个管道的类必须有以下方法:

  • process_item(self,item,spider)
  • open_spider(self,spider)
  • close_spider(self,spider)
  • from_crawler(cls,crawler)

在爬虫开始的时候执行一次,那么我们可以试一下。在pipelines文件中添加open_spider函数,定义一个变量,格式为spider.变量名=变量值。

class MyspiderPipeline(object):

    def open_spider(self,spider):#在爬虫开启的时候执行,仅执行一次
        spider.hello='Hello World!'
 

然后我们就可以在爬虫文件中获取变量值

import scrapy
class MYSpider(scrapy.Spider):
    ...

    def parse(self, response):
        print(self.hello+'*'*100)
 

然后运行我们的爬虫,那么会显示:

Hello World!****************************************************************************************************
 

既然是爬虫开始的时候仅会运行一次,那么可以用来定义一些固定的信息,比方说连接数据库,连接数据库我们通常也是只进行一次。我们可以修改pipelines文件:

from pymongo import MongoClient
class MyspiderPipeline(object):
    def open_spider(self,spider):#在爬虫开启的时候执行,仅执行一次
        client=MongoClient()#实例化连接
        self.collection=client['table']['test']#通过实例创建数据库和表
    def process_item(self, item, spider):
        item=...
        self.collection.insert(dict(item))#插入数据
        return item
 

我们通常要把爬取到的数据保存为文件,比方说json,csv文件,那么我们需要在爬虫开启的时候打开文件爬虫结束的时候关闭文件,文件在爬虫开始的时候打开,在爬虫结束的时候关闭,正好可以使用open_spider和close_spider,具体可以参考代码:

import json
class MyspiderPipeline(object):

    def open_spider(self,spider):#在爬虫开启的时候执行,仅执行一次
        self.file=open(spider.settings.get('SAVE_FILE','./test.json'),'w')
    def close_spider(self,spider):#在爬虫关闭的时候执行,仅执行一次
        self.file.close()
    def process_item(self, item, spider):
        line=json.dumps(dict(item))+"\n"
        self.file.write(line)
        return item  #不return的情况下,另一个权重较低的pipeline就不会获取到item
 

这样就可以保存json文件到本地了,那么如果爬虫爬到一半出错了,数据就不会保存到本地了。这是因为文件写入操作,需要关闭文件,数据才会写入,爬虫出错意味着爬虫没有关闭,也就是文件没有关闭,所以数据的写入可能会丢失。当然你可以使用with open,我也没试过。一般都是把数据保存在数据库中去的,爬虫报错也不会影响数据的丢失。

如何处理多个scrapy爬虫,多个pipeline

通常我们的scrapy爬虫项目是需要有很多个爬虫的,仅仅存在一个爬虫,是不能狗称之为爬虫项目的。当然了,我们在settings配置文件中开启管道的时候就会发现,pipeline是一个字典形式,就是说pipeline可以有多个,而且确实pipeline能够定义多个,那么我们需要知道为什么会有多个pipeline:

  • 1.存在多个spider,不同的pipeline处理不同的item内容
  • 2.一个spider的内容可能要做不同的操作,比方说存入不同的数据库中去

pipeline的权重越小优先级也越高,其中pipeline中的process_item是不可以修改为其他的名字的

scrapy的pipelines.py

import json#存储为json数据吧
class MyspiderPipeline(object):
        def process_item(self, item, spider):  #item是爬虫文件yield出来的数据,实现存储
            with open('filename.txt','a') as f:
                json.dump(item,f,ensure_ascii=False,indent=2)
 

完成pipeline代码之后需要在settings文件开启管道

scrapy的settings.py

# Configure item pipelines
# See https://doc.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
   'myspider.pipelines.ErshoufangPipeline': 300,
   #pipeline的位置                            权重
   #如果存在多个pipeline的话,添加就可以了
}

 

那么我们按照固定的代码来创建一个scrapy爬虫文件:

scrapy startproject myspider #创建一个myspider爬虫
cd myspider #进入myspider文件
scrapy genspider ershou second.zz.fccs.com
scrapy genspider e1yu e1yu.com
scrapy genspider meizi www.lmmpic.com
 

通常一个爬虫项目是需要爬多个网站的,所以我们创建了三个爬虫文件,这三个爬虫文件全部在spiders文件夹下,如果在命令行创建网址需要加引号,网址前面也不要加http。那么爬虫的数据会先到pipeline中,网站的数据不一样,我们处理的方式也就不一样吗,所以就需要多个pipeline来处理,我们可以在pipelines.py文件中进行判断:

class MyspiderPipeline(object):
    def process_item(self, item, spider):
        if ...:
            ...
        else ...:
            ...
        else ...:
            ...
        return item
 

这只是一个格式,具体的判断内容,需要我们在每一个爬虫中自定义一个字段,比方说刚才建的ershoufang爬虫,我们可以在ershoufang爬虫文件这样写:

import scrapy


class ErshoufangSpider(scrapy.Spider):
    name = 'ershoufang'
    allowed_domains = ['http://second.zz.fccs.com/']
    start_urls = ['http://http://second.zz.fccs.com//']

    def parse(self, response):
        item={}
        item['come_from']='ershoufang'
        pass
 

之后我们就可以在pipelines文件中进行判断,对于不同的爬虫,有不同的解析方式。我们可以注意到pipelines中MyspiderPipeline这个类,接收两个参数item和spider,这个spider就是我们的爬虫,那么也可以根据spider的name属性来判断:

class MyspiderPipeline(object):
    def process_item(self, item, spider):
        if spider.name=='ershoufang':
            ...

        return item


class MyspiderPipeline1(object):
    def process_item(self, item, spider):
        if spider.name == 'e1yu':
            ...

        return item


class MyspiderPipeline2(object):
    def process_item(self, item, spider):
        #if item['come_from'] == 'meizi':
        if spider.name == 'meizi':
            ...

        return item

 

未经允许不得转载:作者:鳄鱼君, 转载或复制请以 超链接形式 并注明出处 鳄鱼君
原文地址:《Scrapy深入学习pipelines管道文件》 发布于2020-03-08

分享到:
赞(1) 赏杯咖啡

评论 抢沙发

4 + 4 =


文章对你有帮助可赏作者一杯咖啡

支付宝扫一扫打赏

微信扫一扫打赏

Vieu4.6主题
专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。
切换注册

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录
切换登录

注册