Scrapy之pipeline保存数据

162 阅读3分钟

使用pipeline

从pipeline的字典形可以看出来,pipeline可以有多个,⽽且确实pipeline能够定义多个

为什么需要多个pipeline:

  • 可能会有多个spider,不同的pipeline处理不同的item的内容

  • ⼀个spider的内容可以要做不同的操作,⽐如存⼊不同的数据库中

注意:

  • pipeline的权重越⼩优先级越⾼
  • pipeline中process_item⽅法名不能修改为其他的名称

首先,我们需要在settings.py文件中找到如下部分的代码,并取消注释

图片.png

图片.png

可以有多个MyspiderPipeline类,但是,每增加一个类,都需要在settings.py文件中做出相应的配置

图片.png

说明:后面的数字(300)代表的就是权重,并且数字不能相同

验证pipeline是否能用

我们在代码中需要有生成器

图片.png

在Scrapy爬虫中,yield关键字用于产生一个生成器(generator)。当你在一个函数中使用yield而不是return时,这个函数就变成了一个生成器。每次调用生成器的next()方法(或使用for循环迭代)时,它会执行到下一个yield语句并返回yield后面表达式的值,同时保存当前执行上下文的状态。当下次再次调用时,它会从上次离开的地方继续执行,直到遇到下一个yield或函数结束。

每当解析到一个新闻标题时,就会创建一个包含该标题的字典item,然后通过yield item将其发送出去。这样,Scrapy就可以接收到每一个新闻标题,并根据配置的管道来处理这些标题,比如将它们保存到数据库或文件中。

pipelines.py文件中输入一条打印语句

图片.png

运行爬虫程序,我们可以获取到数据

图片.png

保存为json文件

class MyspiderPipeline:  
    def __init__(self):  
        self.f = open('demo.json', 'w', encoding='UTF-8')  

    def open_spider(self, spider):  
        print("爬虫开始了")  

    def process_item(self, item, spider):  
        print(item)  
        print("文件写入中...")  
        item_json = json.dumps(item, ensure_ascii=False)  
        self.f.write(item_json + "\n")  
        return item  

    def close_spider(self, spider):  
        print("爬虫结束了")  
        self.f.close()

多管道

在我们使用Scrapy时可能会有多个spider,不同的pipeline处理不同的item的内容,那么如何区分item是来自哪个管道呢

关于spider参数:

图片.png

我们打印spider参数就可以看到是属于哪个管道的

我们可以通过spider.name即可获取管道名字,这样使用判断语句即可区分开来

PS E:\Study\code\Python\网络爬虫\ScrapyStudy\mySpider> scrapy genspider jd jd.com
Created spider 'jd' using template 'basic' in module:
  mySpider.spiders.jd
PS E:\Study\code\Python\网络爬虫\ScrapyStudy\mySpider>

我们创建一个关于jd的爬虫,注意:需要修改一下start_urls

方法1:

def process_item(self, item, spider):  
    # 方法1  
    if spider.name == 'xl':  
        print(spider.name)  
        # print(item)  
        # print("文件写入中...")  
        item_json = json.dumps(item, ensure_ascii=False)  
        self.f.write(item_json + "\n")  
        return item

方法2:

item的字典中添加一个come_from字段,用来判断

def parse(self, response):  
    # print("=" * 30)  
    # print(response)  
    # print(type(response))  
    # print("=" * 30)  
    li_list = response.xpath("//div[@class='main-nav']//ul/li/a/text()")  
    # print("获取到:{}个标题".format(len(li_list)))  
    # print(type(li_list))  
    item = {}  
    for li in li_list:  
    item['title'] = li.extract()  
    # print(item)  
    item['come_from'] = 'xl'  
    yield item # 生成器
# 方法2  
print(item['come_from'])  
if item['come_from'] == 'xl':  
return item