【问题标题】:Stream scrapy logging output to websocket将scrapy日志输出流式传输到websocket
【发布时间】:2016-03-01 19:25:36
【问题描述】:

我正在尝试构建一个 API,该 API 将在通过 websocket 消息请求时运行 Scrapy 网络蜘蛛。

我想将日志输出转发到 websocket 客户端,这样您就可以看到 - 有时运行很长时间 - 进程中发生了什么。完成后,我也会发送抓取的结果。

因为可以在进程内运行 Scrapy,所以我想这样做。我在这里找到了一个将外部进程流式传输到 websocket 的解决方案,但如果可以在服务器内部运行 Scrapy,这似乎不正确。

https://tomforb.es/displaying-a-processes-output-on-a-web-page-with-websockets-and-python

我可以想象有两种方法可以在 Twisted 中完成这项工作:以某种方式使用 LogObserver,或者定义一个 LogHandler(可能是带有 StringIO 的 StreamHandler),然后在 Twisted 中使用 autobahn.websocket 类(如 WebSocketServerProtocol)以某种方式处理 Stream。

现在我很困惑,不知道如何连接两端。

有人可以提供一个简短的示例,如何将来自扭曲日志的日志输出(如果可能,避免使用文件)流式传输到 websocket 客户端吗?

【问题讨论】:

    标签: python websocket scrapy twisted


    【解决方案1】:

    我设法自己解决了这个问题,想告诉你我是怎么做到的:

    基本想法是有一个进程被远程调用并将流式日志输出到客户端,通常是浏览器。

    我没有自己构建所有令人讨厌的细节,而是决定使用autobahn.wscrossbar.io,通过Wamp protocol 提供pubsub 和rpc,这基本上只是websockets 上的JSON——正是我计划构建的,只是更高级!

    这是一个非常基本的例子:

    from twisted.internet.defer import inlineCallbacks
    
    from autobahn.twisted.wamp import ApplicationSession
    from example.spiders.basic_spider import BasicSpider
    from scrapy.crawler import CrawlerRunner
    from scrapy.utils.log import configure_logging
    from scrapy.utils.project import get_project_settings
    
    import logging
    
    class PublishLogToSessionHandler(logging.Handler):
        def __init__(self, session, channel):
            logging.Handler.__init__(self)
            self.session = session
            self.channel = channel
    
        def emit(self, record):
            self.session.publish(self.channel, record.getMessage())
    
    
    class AppSession(ApplicationSession):
    
        configure_logging(install_root_handler=False)
    
        @inlineCallbacks
        def onJoin(self, details):
            logging.root.addHandler(PublishLogToSessionHandler(self, 'com.example.crawler.log'))
    
            # REGISTER a procedure for remote calling
            def crawl(domain):
                runner = CrawlerRunner(get_project_settings())
                runner.crawl("basic", domain=domain)
                return "Running..."
    
            yield self.register(crawl, 'com.example.crawler.crawl')
    

    【讨论】:

    • 感谢您跟进您的回答!
    猜你喜欢
    • 2020-07-24
    • 2018-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-13
    • 2020-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多