1

我有多个蜘蛛同时运行的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 文件中,并且蜘蛛正常工作,但是爬取的内容没有反映在公共文件上。Spiders 似乎运行良好,但管道并没有很好地完成它们的工作,并且没有将数据收集到公共文件中。

我还注意到只有一只蜘蛛同时在文件上写。

4

1 回答 1

1

我看不出有什么好的理由去做你所做的事情:) 你可以通过在你的 scrapyd请求json_filename上设置参数来更改设置。schedule.json然后,您可以让每个蜘蛛生成稍微不同的文件,您可以在后处理或查询时合并这些文件。FEED_URI您还可以通过设置值(示例)来编写类似于您所拥有的 JSON 文件。如果您从多个进程同时写入单个文件(尤其是当您使用'wb'模式打开时),您正在寻找损坏的数据。

编辑:

在更好地理解了你需要什么之后 - 在这种情况下 - 它是scrapyd开始运行不同的蜘蛛的多次爬网,每个爬网都爬取不同的网站。消费者进程持续监控单个文件。

有几种解决方案,包括:

  • 命名管道

相对容易实现,仅适用于非常小的项目(见此处

  • RabbitMQ 或其他一些排队机制

很好的解决方案,但可能有点矫枉过正

  • 一个数据库,例如基于 SQLite 的解决方案

很好很简单,但可能需要一些编码(自定义消费者)

  • 基于niceinotifywait的或其他文件系统监控解决方案

很好,可能很容易实现

最后一个对我来说似乎是最有吸引力的选择。完成后scrapy crawlspider_close 信号),将文件移动、复制或创建软链接到您使用这样FEED_URL的脚本监视的目录。或者是一个原子unix操作,所以你应该没问题。修改脚本以将新文件附加到您曾经提供给消费者程序的文件上。mvlntmp

通过这种方式,您可以使用默认的 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,
}
于 2016-03-24T16:32:02.370 回答