文章目录
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
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()