我有2只蜘蛛在这里运行:
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings
settings = get_project_settings()
process1 = CrawlerProcess(settings)
process1.crawl('spider1')
process1.crawl('spider2')
process1.start()
我想让这些蜘蛛写一个共同的文件。
这是Pipeline类:
class FilePipeline(object):
def __init__(self):
self.file = codecs.open('data.txt', 'w', encoding='utf-8')
self.spiders = []
def open_spider(self, spider):
self.spiders.append(spider.name)
def process_item(self, item, spider):
line = json.dumps(OrderedDict(item), ensure_ascii=False, sort_keys=False) + "\n"
self.file.write(line)
return item
def spider_closed(self, spider):
self.spiders.remove(spider.name)
if len(self.spiders) == 0:
self.file.close()
但是虽然我没有收到错误消息,但是当所有蜘蛛都在公共文件中写入时,我的行(项目)比scrapy日志少。切几条线。也许有一些练习同时从两个蜘蛛写入一个文件?
更新:
谢谢大家!) 我这样实现了它:
class FilePipeline1(object):
lock = threading.Lock()
datafile = codecs.open('myfile.txt', 'w', encoding='utf-8')
def __init__(self):
pass
def open_spider(self, spider):
pass
def process_item(self, item, spider):
line = json.dumps(OrderedDict(item), ensure_ascii=False, sort_keys=False) + "\n"
try:
FilePipeline1.lock.acquire()
if isinstance(item, VehicleItem):
FilePipeline1.datafile.write(line)
except:
pass
finally:
FilePipeline1.lock.release()
return item
def spider_closed(self, spider):
pass
答案 0 :(得分:2)
我同意A. Abramov的回答。
这只是我的想法。您可以在您选择的数据库中创建两个表,然后在两个蜘蛛完成爬网后合并它们。您必须跟踪日志进入的时间,以便您可以根据收到的时间订购日志。然后,您可以将db转储到您想要的任何文件类型。这样,程序在写入文件之前不必等待一个进程完成,并且您不必进行任何多线程编程。
更新:
实际上,根据蜘蛛运行的时间长短,您可以将日志输出和时间存储到字典中。时间是键,日志输出是值。这比初始化db更容易。然后,您可以按键将dict转储到文件中。
答案 1 :(得分:1)
你在单独的线程中拥有的两个蜘蛛同时写入文件。正如past所说,会会导致诸如线路切断等问题,如果你不处理同步问题,其中一些会丢失。为了做到这一点,你需要同步文件访问并只写整个记录/行,或者有一个策略来分配文件的区域到不同的线程,例如重新构建具有已知偏移和大小的文件,默认情况下,您没有这些文件。一般来说,同时从两个不同的线程写入同一个文件并不是一种常用的方法,除非你真的知道你在做什么,否则我不建议你这样做。
相反,我要分离蜘蛛IO功能,等待一个人的行动完成,然后才开始另一个 - 考虑到你的线程没有同步,这将使程序更多高效的让它工作:)如果你想要一个代码示例,说明如何在你的上下文中这样做,只需要它,我会乐意提供它。