我有几台蜘蛛同时运行的scrapyd服务器,我使用schedule.json端点逐个启动蜘蛛。所有蜘蛛都使用管道在公共文件上写内容
class JsonWriterPipeline(object):
def __init__(self, json_filename):
# self.json_filepath = json_filepath
self.json_filename = json_filename
self.file = open(self.json_filename, 'wb')
@classmethod
def from_crawler(cls, crawler):
save_path='/tmp/'
json_filename=crawler.settings.get('json_filename', 'FM_raw_export.json')
completeName = os.path.join(save_path, json_filename)
return cls(
completeName
)
def process_item(self, item, spider):
line = json.dumps(dict(item)) + "\n"
self.file.write(line)
return item
蜘蛛运行后我可以看到他们如何正确收集数据,项目存储在文件XXXX.jl中,蜘蛛工作正常,但是爬行的内容不会反映在普通文件中。蜘蛛似乎运行良好,但是管道不能很好地完成工作,并且没有将数据收集到公共文件中。
我也注意到只有一只蜘蛛在同一时间写作文件。
答案 0 :(得分:1)
我没有任何理由去做你做的事情:)你可以通过在scrapyd json_filename
请求上设置参数来更改schedule.json
设置。然后,您可以使每个蜘蛛生成稍微不同的文件,您可以将这些文件与后处理或查询时合并。您还可以通过设置FEED_URI
值(example)来编写类似于您所拥有的JSON文件。如果您同时从多个进程写入单个文件(特别是当您使用'wb'
模式打开时),那么您正在寻找损坏的数据。
编辑:
在更好地了解您所需要的内容之后 - 在这种情况下 - 它的scrapyd开始多次抓取,运行不同的蜘蛛,每个抓取一个不同的网站。消费者进程持续监视单个文件。
有几种解决方案,包括:
相对容易实现,只适用于非常小的项目(see here)
很好的解决方案,但可能有点矫枉过正
既简单又简单,但可能需要一些编码(自定义消费者)
inotifywait
或其他文件系统监控解决方案很好,很容易实现
最后一个对我来说似乎是最有吸引力的选择。当scrapy crawl
完成(spider_closed signal)后,将FEED_URL
文件的软链接移动,复制或创建到您使用this等脚本监控的目录。 mv
或ln
是一个原子unix操作,所以你应该没问题。破解脚本,将新文件附加到您为消费者计划提供一次的tmp
文件中。
通过这种方式,您可以使用默认的Feed导出程序来编写文件。最终解决方案非常简单,您不需要管道。一个简单的扩展应符合该法案。
在与extensions.py
相同的目录中的settings.py
上:
from scrapy import signals
from scrapy.exceptions import NotConfigured
class MoveFileOnCloseExtension(object):
def __init__(self, feed_uri):
self.feed_uri = feed_uri
@classmethod
def from_crawler(cls, crawler):
# instantiate the extension object
feed_uri = crawler.settings.get('FEED_URI')
ext = cls(feed_uri)
crawler.signals.connect(ext.spider_closed, signal=signals.spider_closed)
# return the extension object
return ext
def spider_closed(self, spider):
# Move the file to the proper location
# os.rename(self.feed_uri, ... destination path...)
在settings.py
上:
EXTENSIONS = {
'myproject.extensions.MoveFileOnCloseExtension': 500,
}