我正在使用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脚本中完成?
答案 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()