暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

NO.14 Scrapy 将数据存入 MongoDB

嘉乐Ae小课堂 2020-12-22
556

点击上方蓝字,获得更多精彩内容

      

      有时,我们想把爬取到的数据存入某种数据库中,可以实现 Item Pipeline 完成此类任务。下面实现一个能将数据存入 MongoDB 数据库的 Item Pipeline,创建 demo5 项目(与demo4相同),实现 MongoDBPipeline类,代码如下:

    from scrapy.item import Item
    import pymongo


    class MongoDBPipeline(object):


    DB_URI = 'mongodb://localhost:27017/'
    DB_NAME = 'scrapy_data'


    def open_spider(self, spider):
    self.client = pymongo.MongoClient(self.DB_URI)
    self.db = self.client[self.DB_NAME]


    def close_spider(self, spider):
    self.client.close()


    def process_item(self, item, spider):
    collection = self.db[spider.name]
    post = dict(item) if isinstance(item, Item) else item
    collection.insert_one(post)
    return item

    对上述代码解释如下:

    • 在类属性中定义两个常量:

      ① DB_URI:数据库的 URI 地址。

      ② DB_NAME:数据库的名字。

    • 在 Spider 整个爬取过程中,数据库的连接和关闭操作只需要进行一次,应该在开始处理数据之前连接数据库,并在处理完所有数据之后关闭数据库,因此实现以下两个方法(在 Spider 打开和关闭时被调用):

      ① open_spider(self, spider)

      ② close_spider(self, spider)

      分别在 open_spider 和 close_spider 方法中实现数据库的连接与关闭。

    • 在 process_item 中实现 MongoDB 数据库的写入操作,使用 self.db 和 spider.name 获取一个集合(collection),然后将数据插入该集合,集合对象的 insert_one 方法需要传入一个字典对象(不能传入 Item 对象),因此在调用前先对 item 的类型进行判断,如果 item 是 Item 对象,就将其转换为字典。



    下一步,我们在 Robo 3T 中创建一个名为“scrapy_data”的数据库:


    接下来测试 MongoDBPipeline ,在配置文件 settings.py 中启用 MongoDBPipeline

      ITEM_PIPELINES = {
      'demo5.pipelines.PriceConverterPipeline': 300,
      'demo5.pipelines.DuplicatesPipeline': 350,
      'demo5.pipelines.MongoDBPipeline': 400,
      }

      执行以下命令运行爬虫,并查看数据库中的结果:

        scrapy crawl books


        在上述实现中,数据库的 URI 地址和数据库的名字硬编码在代码中,如果希望通过配置文件设置它们,只需要稍作改动,代码如下:
          from scrapy.item import Item
          import pymongo


          class MongoDBPipeline(object):


          # 直接定义方式
          # DB_URI = 'mongodb://localhost:27017/'
          # DB_NAME = 'scrapy_data'


          # 配置文件方式
          # 类方法(不需要实例化类就可以被类本身调用)
          @classmethod
          def from_crawler(cls, crawler):
          cls.DB_URI = crawler.settings.get('MONGO_DB_URI', 'mongodb://localhost:27017/')
          cls.DB_NAME = crawler.settings.get('MONGO_DB_NAME', 'scrapy_data2')
          return cls()


          def open_spider(self, spider):
          self.client = pymongo.MongoClient(self.DB_URI)
          self.db = self.client[self.DB_NAME]


          def close_spider(self, spider):
          self.client.close()


          def process_item(self, item, spider):
          collection = self.db[spider.name]
          post = dict(item) if isinstance(item, Item) else item
          collection.insert_one(post)
          return item

          对上述改动解释如下:
          • 增加类方法 from_crawler(cls, crawler),替代在类属性中定义 DB_URI  和 DB_NAME 。

          • 如果一个 Item Pipeline 定义了 from_crawler 方法,Scrapy 就会调用该方法来创建 Item Pipeline 对象。该方法有两个参数:

            ① cls:Item Pipeline 类的对象(这里为 MongoDBPipeline 类对象)。

            ② crawler:Crawler 是 Scrapy 中的一个核心对象,可以通过 crawler 的 settings 属性访问配置文件。

          • 在 from_crawler 方法中,读取配置文件中的 MONGO_DB_URI 和 MONGO_DB_NAME (不存在使用默认值),赋给 cls 的属性,即 MongoDBPipeline 类属性。

          • classmethod 修饰符对应的函数不需要实例化,不需要 self 参数,但第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象等。

          • 其他代码并没有任何改变,因为这里只是改变了设置 MongoDBPipeline 类属性的方式。


          现在,我们可以在配置文件 settings.py 中对所要使用的数据库进行设置:
            MONGO_DB_URI = 'mongodb://localhost:27017/'
            MONGO_DB_NAME = 'scrapy_data2'

            重新执行以下命令运行爬虫,并查看数据库中的结果:

              scrapy crawl books

              查看scrapy_data2数据库,数据已经正常存入。



              内容参考:

              Scrapy官方文档、《精通Scrapy网络爬虫》、百度



              END




              这里“阅读原文”,查看github中的代码

              文章转载自嘉乐Ae小课堂,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

              评论