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

scrapy使用多个item

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

自己的第一个问题 yield

xin_spider.py


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):

    name = scrapy.Field()
    age = scrapy.Field()

class ScrapyShiyanItem_2(scrapy.Item):

    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'])

        return item

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

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


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

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

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

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
20
第2个管道类
第一个items模型类的输出:
xiaoming
20
第一个管道类
第二个items模型类的输出:
daming
25
第2个管道类
第二个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
20
第2个管道类
第二个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()

Original: https://blog.csdn.net/weixin_44505901/article/details/115931575
Author: 王轩12
Title: scrapy中多个spider文件和多个items.py以及多个管道文件之间的对应



相关阅读

Title: 阿里天池数据分析入门 利用Pandas分析数据

pd.read_csv用法

ccl = pd.read_csv("1_usa_candidate/ccl.txt", sep = '|',names=['CAND_ID','CAND_ELECTION_YR','FEC_ELECTION_YR','CMTE_ID','CMTE_TP','CMTE_DSGN','LINKAGE_ID'])

sep = ‘|’

sep

读取csv文件时指定的分隔符,默认为逗号。注意:”csv文件的分隔符” 和 “我们读取csv文件时指定的分隔符” 一定要一致。本题中提供的数据分隔符是’|’所以按代码设置,names 将每列的名字加上。

names

  • 当names没被赋值时,header会变成0,即选取数据文件的第一行作为列名。(从0开始计数)
  • *当 names 被赋值,header 没被赋值时,那么header会变成None。如果都赋值,就会实现两个参数的组合功能

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

pd.merge()函数介绍

ccl =pd.merge(candidates,ccl)

scrapy中多个spider文件和多个items.py以及多个管道文件之间的对应 能够看出这两个表中的员工是同一批人,而且两个表中也只有”CAND_ID”一列重复列,一般这种情况直接用pd.merge()拼接不用指定主键,直接把一个表的名字传递给参数left,另一个表的名字传递给参数right就可以了。合并之后CAND_ID这列只有一列,其他列是两个表合并在一起的列。

扩展知识看这个:merge函数详解

DataFrame

DataFrame是Python中Pandas库中的一种数据结构,它类似excel,是一种二维表。

直观理解: DataFrame 是带标签的二维数组

pd.DataFrame(data=None, index=None, columns=None)

ccl =pd.DataFrame(ccl, columns=[ 'CMTE_ID','CAND_ID', 'CAND_NAME','CAND_PTY_AFFILIATION'])

这里从ccl数据表中选中其中的四列,index使用默认的。

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

fillna()函数

#空值处理,统一填充 NOT PROVIDED
c_itcont['STATE'].fillna('NOT PROVIDED',inplace=True)#fillna函数 填充空值
c_itcont['EMPLOYER'].fillna('NOT PROVIDED',inplace=True)
c_itcont['OCCUPATION'].fillna('NOT PROVIDED',inplace=True)

inplace参数的取值:True、False

True:直接修改原对象

False:创建一个副本,修改副本,原对象不变(缺省默认)

Groupby函数

c_itcont.groupby("CAND_PTY_AFFILIATION").sum().sort_values("TRANSACTION_AMT",ascending=False).head(10)

kind = bar

当使用.plot()绘制Pandas DataFrame时,

默认的 .plot()用直线连接所有数据点并生成线图。

另一方面, .plot(kind='bar')每个_数据点绘制为 _离散条形。为了在x轴上获得正确的格式,必须在绘图后修改刻度标签。

# 各州捐款总人数可视化,取前10个州的数据
st_amt = c_itcont.groupby('STATE').size().sort_values(ascending=False).head(10)
st_amt.plot(kind='bar')

scrapy中多个spider文件和多个items.py以及多个管道文件之间的对应kind =bar 是图的类型,line参数表示折线图

参数 说明
label 用于图例的标签
ax 要在其上进行绘制的matplotlib subplot对象。如果没有设置,则使用当前matplotlib subplot
style 将要传给matplotlib的风格字符串(for example: ‘ko–’)
alpha 图表的填充不透明(0-1)
kind 可以是’line’, ‘bar’, ‘barh’, ‘kde’
logy 在Y轴上使用对数标尺
use_index 将对象的索引用作刻度标签
rot 旋转刻度标签(0-360)
xticks 用作X轴刻度的值
yticks 用作Y轴刻度的值
xlim X轴的界限
ylim Y轴的界限
grid 显示轴网格线

Original: https://blog.csdn.net/MANNYX/article/details/120731139
Author: MANNYX
Title: 阿里天池数据分析入门 利用Pandas分析数据

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/351277/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

最近整理资源【免费获取】:   👉 程序员最新必读书单  | 👏 互联网各方向面试题下载 | ✌️计算机核心资源汇总