Scrapy Spider完成后,如何触发Mongodb导入?

时间:2018-09-22 17:25:46

标签: python mongodb web-scraping scrapy upsert

我正在使用Scrapy(Python库)来抓取网站并定期生成json输出文件。 为了提高效率,我想在每个蜘蛛完成后将这些json文件批量上传到Mongodb中。

我相信我可以这样做:

mongoimport -c <collection> -d <db> --mode merge --file test.json

但是,我想知道蜘蛛完成后触发此导入的最佳方法是什么?又如何?

我希望我可以使用此处描述的close_spider方法: https://doc.scrapy.org/en/latest/topics/item-pipeline.html#writing-your-own-item-pipeline

但是,在使用它之后,我发现仅创建了json文件,而在此方法中时未写入json文件。

如果我有某种方法可以侦听某个目录中的新文件,然后执行上面的import语句,那将很好。

也许这一切都可以在bash脚本中完成?

3 个答案:

答案 0 :(得分:0)

您可以使用 Item Pipelines 将项目直接写入Mongo。从Scrapy's documentation看这个示例:

  

将项目写入MongoDB

     

在此示例中,我们将使用pymongo将项目写入MongoDB。在Scrapy设置中指定了MongoDB地址和数据库名称; MongoDB集合以项目类命名。

     

此示例的重点是显示如何使用from_crawler()方法以及如何正确清理资源。

import pymongo

class MongoPipeline(object):

    collection_name = 'scrapy_items'

    def __init__(self, mongo_uri, mongo_db):
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            mongo_uri=crawler.settings.get('MONGO_URI'),
            mongo_db=crawler.settings.get('MONGO_DATABASE', 'items')
        )

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

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

    def process_item(self, item, spider):
        self.db[self.collection_name].insert_one(dict(item))
        return item

答案 1 :(得分:0)

此方法对我有用(在您的蜘蛛文件中):

Cart

答案 2 :(得分:0)

一种解决方案是使用pyinotify监视所选目录中的文件。我从here那里得到了这个想法,并对其进行了修改以执行mongo import语句。

class MyEventHandler(pyinotify.ProcessEvent):

    def process_IN_ACCESS(self, event):
        print("ACCESS event:", event.pathname)

    def process_IN_ATTRIB(self, event):
        print("ATTRIB event:", event.pathname)

    def process_IN_CLOSE_NOWRITE(self, event):
        print("CLOSE_NOWRITE event:", event.pathname)

    def process_IN_CLOSE_WRITE(self, event):
        print("CLOSE_WRITE event:", event.pathname)
        result = os.system('mongoimport -c kray4 -d kray4 --mode merge --file /home/kevin/PycharmProjects/spider/krawler/output/test.json')
        print("Result: " + str(result))

    def process_IN_CREATE(self, event):
        print("CREATE event:", event.pathname)

    def process_IN_DELETE(self, event):
        print("DELETE event:", event.pathname)

    def process_IN_MODIFY(self, event):
        print("MODIFY event:", event.pathname)

    def process_IN_OPEN(self, event):
        print("OPEN event:", event.pathname)


def main():
    # watch manager
    wm = pyinotify.WatchManager()

    wm.add_watch('/home/kevin/PycharmProjects/spider/krawler/output/test.json', pyinotify.ALL_EVENTS, rec=True)

    # event handler
    eh = MyEventHandler()

    # notifier
    notifier = pyinotify.Notifier(wm, eh)
    #command = 'echo 1 > /proc/sys/net/ipv4/ip_forward'
    notifier.loop()

if __name__ == '__main__':
    main()