scrapy中多个spider文件和多个items.py以及多个管道文件之间的对应

scrapy中多个spider文件和多个items.py以及多个管道文件之间的对应

scrapy使用多个item

scrapy爬虫常见问题
scrapy使用多个item以及指定item进行json输出

一个spider文件对应多个多个items模型类


自己的第一个问题 yield

xin_spider.py

# -*- coding: utf-8 -*-
import scrapy
from scrapy_shiyan.items import ScrapyShiyanItem, ScrapyShiyanItem_2

class XinSpiderSpider(scrapy.Spider):
    name = 'xin_spider'
    allowed_domains = ['xinfadi.com.cn']
    start_urls = ['http://xinfadi.com.cn/']

    def parse(self, response):

        items = ScrapyShiyanItem()
        items['name'] = 'xiaoming'
        items['age'] = 20



        yield items

        items2 = ScrapyShiyanItem_2()
        items2['name2'] = 'daming'
        items2['age2'] = 25


        items['name'] = 'xiaoming22'
        items['age'] = 202
        yield items

        """
        可以在 yield items 后再写,自己认为的  执行到yield items后,
        这个函数就结束了,是不对的,可以写多个yield items
        
        输出:
        
        第一个管道类
        第一个items模型类的输出:
        xiaoming
        20
        第一个管道类
        {'age': 20, 'name': 'xiaoming'}
        第一个items模型类的输出:
        xiaoming22
        202
        
        """


items.py

import scrapy


class ScrapyShiyanItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    name = scrapy.Field()
    age = scrapy.Field()


class ScrapyShiyanItem_2(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    name2 = scrapy.Field()
    age2 = scrapy.Field()

pipelines.py


class ScrapyShiyanPipeline(object):
    def process_item(self, item, spider):
        print("第一个管道类")
        print("第一个items模型类的输出:")
        print(item['name'])
        print(item['age'])



        # print(item['name2'])
        # print(item['age2'])
        return item


如上代码中,items.py文件中有两个模型类
那么如何在一个管道文件中使用分别使用这两个模型类呢?

如下代码,就会遇到这个问题:
xin_spider.py

# -*- coding: utf-8 -*-
import scrapy
from scrapy_shiyan.items import ScrapyShiyanItem, ScrapyShiyanItem_2

class XinSpiderSpider(scrapy.Spider):
    name = 'xin_spider'
    allowed_domains = ['xinfadi.com.cn']
    start_urls = ['http://xinfadi.com.cn/']

    def parse(self, response):

        items = ScrapyShiyanItem()
        items['name'] = 'xiaoming'
        items['age'] = 20

        yield items

        items2 = ScrapyShiyanItem_2()
        items2['name2'] = 'daming'
        items2['age2'] = 25

        yield items2    # 注意这里返回的是 items2

       

items.py 不变同上


pipelines.py


class ScrapyShiyanPipeline(object):
    def process_item(self, item, spider):
        print("第一个管道类")
        print("第一个items模型类的输出:")
        print(item['name'])
        print(item['age'])


		print("第一个管道类")
        print("第二个items模型类的输出:")
        print(item['name2'])
        print(item['age2'])
        return item

如果这样运行的话会报错:
报 KeyError: 'name2' 和KeyError: 'name'

因为  yield items 时将 第一个模型类的数据传入 管道文件中
在管道文件中 有提取出模型类中的字段,
当 运行到 print(item['name2'])时,就会报KeyError: 'name2'

因为在ScrapyShiyanItem 第一个模型类中,我们只是定义了,name和age
所以程序没有在模型类中找到 name2, 

这就是使用多个模型类时会遇到的问题,
需要在管道文件中加个判断条件,判断 item是来自哪个模型类的,
然后根据不同模型类进行数据提取

如下:

修改管道文件


from scrapy_shiyan.items import ScrapyShiyanItem, ScrapyShiyanItem_2
# 注意一定要在pipelines.py中导入items.py文件中的类
class ScrapyShiyanPipeline(object):
    def process_item(self, item, spider):
        if isinstance(item, ScrapyShiyanItem):

            print("第一个管道类")
            print("第一个items模型类的输出:")
            print(item['name'])
            print(item['age'])

        elif isinstance(item, ScrapyShiyanItem_2):
            print("第一个管道类")
            print("第二个items模型类的输出:")
            print(item['name2'])
            print(item['age2'])


        return item


输出:


第一个管道类
第一个items模型类的输出:
xiaoming
20
第一个管道类
第二个items模型类的输出:
daming
25



如果有多个管道类呢,呢


from scrapy_shiyan.items import ScrapyShiyanItem, ScrapyShiyanItem_2
# 注意一定要在pipelines.py中导入items.py文件中的类
class ScrapyShiyanPipeline(object):
    def process_item(self, item, spider):
        if isinstance(item, ScrapyShiyanItem):

            print("第一个管道类")
            print("第一个items模型类的输出:")
            print(item['name'])
            print(item['age'])

        elif isinstance(item, ScrapyShiyanItem_2):
            print("第一个管道类")
            print("第二个items模型类的输出:")
            print(item['name2'])
            print(item['age2'])


        return item



class ScrapyShiyanPipeline_2(object):
    def process_item(self, item, spider):
        if isinstance(item, ScrapyShiyanItem):

            print("第2个管道类")
            print("第一个items模型类的输出:")
            print(item['name'])
            print(item['age'])

        elif isinstance(item, ScrapyShiyanItem_2):
            print("第2个管道类")
            print("第二个items模型类的输出:")
            print(item['name2'])
            print(item['age2'])


        return item

此时就会输出:

第一个管道类
第一个items模型类的输出:
xiaoming
202个管道类
第一个items模型类的输出:
xiaoming
20
第一个管道类
第二个items模型类的输出:
daming
252个管道类
第二个items模型类的输出:
daming
25

这就是每一个管道类都会输出,数据被输出了两遍

一个spider爬虫文件对应多个管道类

可以在spider中加上,如下代码,为spider指定管道类

 custom_settings = {
        'ITEM_PIPELINES': {'scrapy_shiyan.pipelines.ScrapyShiyanPipeline_2': 400,},

    }  # 设置将优先并覆盖项目

如下:

import scrapy
from scrapy_shiyan.items import ScrapyShiyanItem, ScrapyShiyanItem_2

class XinSpiderSpider(scrapy.Spider):
    name = 'xin_spider'
    allowed_domains = ['xinfadi.com.cn']
    start_urls = ['http://xinfadi.com.cn/']

    custom_settings = {
        'ITEM_PIPELINES': {'scrapy_shiyan.pipelines.ScrapyShiyanPipeline_2': 400,},

    }  # 设置将优先并覆盖项目

再次运行就会只使用 ScrapyShiyanPipeline_2 管道类了
输出如下:

2个管道类
第一个items模型类的输出:
xiaoming
202个管道类
第二个items模型类的输出:
daming
25

这里又出现一个问题:
就是在一个spider文件中,写爬取了3个网站的代码,那么该如何指定这3个网站的数据,
传输到不同的3个管道类中呢?

我想这样的话,可以在items中加入一项数据,用来判断传到管道中的数据来自哪一个网站,




## 如果是多个spider文件的话如何对应一个管道类
class XinSpiderSpider(scrapy.Spider):
    name = 'xin_spider'
    allowed_domains = ['xinfadi.com.cn']
    start_urls = ['http://xinfadi.com.cn/']

不同的spider文件就会有不同的 name值,如上代码中的name,
用来标识不同的爬虫文件,
可以在一个管道类中,根据name的值来判断,这个数据是来自哪一个爬虫文件的

class ScrapyShiyanPipeline(object):
    def process_item(self, item, spider):
        if spider.name=='xin_spider':
            if isinstance(item, ScrapyShiyanItem):
    
                print(item['spider'])
                print("第一个管道类")
                print("第一个items模型类的输出:")
                print(item['name'])
                print(item['age'])
    
            elif isinstance(item, ScrapyShiyanItem_2):
                print("第一个管道类")
                print("第二个items模型类的输出:")
                print(item['name2'])
                print(item['age2'])
                
        elif spider.name=='xin_spider_2':
            if isinstance(item, ScrapyShiyanItem):
    
                print(item['spider'])
                print("第一个管道类")
                print("第一个items模型类的输出:")
                print(item['name'])
                print(item['age'])
    
            elif isinstance(item, ScrapyShiyanItem_2):
                print("第一个管道类")
                print("第二个items模型类的输出:")
                print(item['name2'])
                print(item['age2'])


        return item




如果是多个spider文件的话如何对应多个管道类

就是在不同的spider文件中,加上

 custom_settings = {
        'ITEM_PIPELINES': {'scrapy_shiyan.pipelines.ScrapyShiyanPipeline_2': 400,},

    }  # 设置将优先并覆盖项目

给不同的spider文件配置不同的管道

多个spider文件同时运行

之前在爬虫项目根目录下写过一个py文件,内容如下:

from scrapy import cmdline
cmdline.execute("scrapy crawl xin_spider --nolog".split())

可以直接点击运行此py文件就可以启动爬虫
如果想运行多个爬虫也可以这样写:如下:

from scrapy import cmdline
cmdline.execute("scrapy crawl xin_spider --nolog".split())
cmdline.execute("scrapy crawl xin_spider_2 --nolog".split())

但是这样写是,先将 xin_spider 爬虫跑完之后,在跑xin_spider_2

所以我们需要一个真正能够同时并行运行多个爬虫文件的方法:
如下,(也是在根目录下新建一个py文件)

from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings

settings = get_project_settings()

crawler = CrawlerProcess(settings)

crawler.crawl('爬虫名1')
crawler.crawl('爬虫名2')

crawler.start()


  • 7
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值