[Python数据采集]Scrapy数据库保存与文件重命名

「这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战

前言

在上篇文章中[Python数据采集]Scrapy实现图片下载,介绍了如何使用Scarpy的pipelines实现了将爬取到的图片进行保存的操作。

本文将上文的基础上作进一步拓展,实现爬虫数据的入库和图片文件的重命名操作。

items

在将数据传给pipelines之前,我们需要修改items,为pipelines提供需要的数据,例如:前面提到的图片url。

这里以爬取电影排名为例:

电影排名信息可能会出现下列字段:
排名、电影名称、导演、演员简介、电影评分、电影封面等。

通过上述信息,我们就可以构建出电影信息item:

class MovieItem(scrapy.Item):
    # define the fields for your item here like:
    name = scrapy.Field()
    director = scrapy.Field()
    actor = scrapy.Field()
    introduction = scrapy.Field()
    score = scrapy.Field()
    image = scrapy.Field()
    url = scrapy.Field()
复制代码

数据库保存

数据库的实现,在前面的文章中也讲过了,需要进行修改的,就是将参数从item中调出来,其他的和前面介绍的一模一样。

class DBPipeline:
   from mysql import DB
   from settings import DB_CONFIG
   db = DB(DB_CONFIG['host'], DB_CONFIG['port'], DB_CONFIG['user'], DB_CONFIG['passwd'])

   def __init__(self):
       self.db.driver.execute('use spider')
       self.db.driver.execute('drop table if exists movies')
       sql_create_table = """一堆建表的sql语句"""
       self.db.driver.execute(sql_create_table)

   def process_item(self, item, spider):
       sql_insert = f'insert into movies(...) values (...)'
       self.db.driver.execute(sql_insert)
       self.db.connection.commit()
       return item
复制代码

图片保存与重命名

在图片保存方面,和上篇文章其实是一模一样的,但是我们发现,默认的Pipeline已经在前面数据库连接的使用过了。

然而,scrapy的图片保存操作使用的pipeline,是需要继承自scrapy.ImagePipline的,若进行了继承,就会在__init__中产生冲突。

因此,此时我们可以新开一个pipeline:

class DownloadImagePipeline(ImagesPipeline):
    def get_media_requests(self, item, info):
        print("正在保存:", item['url'])
        yield Request(item['url'])

    def item_completed(self, results, item, info):
        # 重命名
        path = [x["path"] for ok, x in results if ok]
        # os模块重命名
        os.rename(IMAGES_STORE + "\\" + path[0], IMAGES_STORE + "\\" + str(item['name']) + '.jpg')
复制代码

针对图片保存,我们可以对item_completed函数进行覆写,该函数会在某一图片完成下载后进行触发,此时,使用os模块,就可以实现对其的重命名操作。

配置

由于一次使用了多个Pilelines,因此在设置中,也一定要把所有需要使用的pipelines进行设置开放。
# setting.py
ITEM_PIPELINES = {
   'session_3.pipelines.DBPipeline': 300,
   'session_3.pipelines.DownloadImagePipeline': 300,
}
复制代码