python - 如何将 Scrapy 管道中的批量更新写入 mongodb
问题描述
我有一个基于 Scrapy 的持续运行的爬虫。
在每次运行中,此爬虫都会对给定 ID 列表执行请求,并将输出写入 S3 存储桶。
这些请求可能会不时失败,我需要记录成功和失败。
我目前正在产生一个成功的项目和一个特殊的 ErrorItem 失败。
我制作了一个应该处理成功和失败日志的管道。
def process_item(self, item, spider):
if isinstance(item, MyErrorItem):
self.errors.append(item['id'])
raise DropItem('Dropped')
else:
self.success.append(item['id'])
return item
def close_spider(self, spider):
conn_to_mongo = getconn()
errors_query = create_or_query_by_ids(self.errors)
write_to_mongo(errors_query, {"$set": {"status": "fail"}})
success_query = create_or_query_by_ids(self.success)
write_to_mongo(success_query, {"$set": {"status": "success"}})
我没有找到对这种模式的任何参考。通常所有对外部数据引擎的写入都是由 process_item 函数完成的。
在这里,我将 id 收集到相应的列表中,并在 close_spider 上批量写入。
原因是对数据库执行多个写入请求是没有效率的,如果这可以批量完成的话。
是否有更有效的方法来实现这种行为?这种方法有什么陷阱吗?
解决方案
我不认为这种方法有什么大问题。我能想到的一些缺点:
- 您在内存中保留 2 个列表,这些列表在蜘蛛运行时会不断增长。如果列表变大,这可能会成为问题。如果您逐项进行插入,则不会有这个。
- 如果最后插入错误,您将丢失所有已抓取的数据。例如,如果在您要插入数据时数据库不可用或过载,则必须再次运行蜘蛛
我认为更好的方法可能如下:
- 项目管道写入 json 文件而不是附加到列表
- 在关闭蜘蛛时,您基于 json 文件而不是列表进行插入
这样你就不会超载内存,如果最后插入失败,你可以根据文件重试它,而不必再次重新运行所有内容。
推荐阅读
- javascript - 尝试获取多个图像时,Angular observable 抛出状态码为 200 的错误
- android - 在图表上绘制 BLE 实时数据
- java - 使用 JCabi Java 读取 UTF-16 XML 文件
- javascript - RequireJS:“express”和“cors”的脚本错误,但不知道如何修复它
- bash - 在循环中询问用户输入,直到在命令行参数数组中找到匹配项
- ios - 如何修改现有的 iOS 应用程序以支持拆分视图
- html - 输入从哪里获得额外的宽度?
- python - Visual Studio Code 和 Autopep8 格式化程序
- python - 求解微分方程时,Numba prange 函数比范围慢
- javascript - 如何在不增加小时数的情况下将 GTM-0006 转换为 ISO