【问题标题】:Scrapy request+response+download timeScrapy请求+响应+下载时间
【发布时间】:2023-03-14 07:59:01
【问题描述】:

UPD:不是很接近的问题,因为我认为我的方式不够清晰

是否可以获得当前请求+响应+下载时间以将其保存到项目?

在“普通”python中我这样做

start_time = time()
urllib2.urlopen('http://example.com').read()
time() - start_time

但是我怎么能用 Scrapy 做到这一点呢?

UPD

解决方案对我来说足够了,但我不确定结果的质量。如果你有很多连接超时错误Download time可能是错误的(甚至是DOWNLOAD_TIMEOUT * 3)

对于

settings.py

DOWNLOADER_MIDDLEWARES = {
    'myscraper.middlewares.DownloadTimer': 0,
}

中间件.py

from time import time
from scrapy.http import Response


class DownloadTimer(object):
    def process_request(self, request, spider):
        request.meta['__start_time'] = time()
        # this not block middlewares which are has greater number then this
        return None

    def process_response(self, request, response, spider):
        request.meta['__end_time'] = time()
        return response  # return response coz we should

    def process_exception(self, request, exception, spider):
        request.meta['__end_time'] = time()
        return Response(
            url=request.url,
            status=110,
            request=request)

def parse(... 中的 spider.py 内部

log.msg('Download time: %.2f - %.2f = %.2f' % (
    response.meta['__end_time'], response.meta['__start_time'],
    response.meta['__end_time'] - response.meta['__start_time']
), level=log.DEBUG)

【问题讨论】:

    标签: scrapy


    【解决方案1】:

    你可以写一个Downloader Middleware 来为每个请求计时。它会在请求发出之前添加一个开始时间,然后在它完成时添加一个完成时间。通常,诸如此类的任意数据存储在Request.meta 属性中。此时间信息稍后可能会被您的蜘蛛读取并添加到您的项目中。

    这个下载器中间件听起来对很多项目都很有用。

    【讨论】:

    • 但考虑到请求是异步调度的,下载器中间件可能会在请求实际启动前几秒钟处理这些请求。除非我遗漏了一些东西,否则这种使用下载器中间件的方法实际上并不奏效。
    【解决方案2】:

    不确定您是否需要一个中间件。 Scrapy 有一个 request.meta,你可以查询和生成。对于下载延迟,只需让步

    download_latency=response.meta.get('download_latency'),
    

    获取响应所花费的时间量,因为请求已 已启动,即通过网络发送的 HTTP 消息。这个元键 仅在下载响应后才可用。尽管 大多数其他元键用于控制 Scrapy 行为,这个是 应该是只读的。

    【讨论】:

      【解决方案3】:

      我认为最好的解决方案是使用 scrapy 信号。每当请求到达下载器时,它就会发出 request_reached_downloader 信号。下载后它会发出 response_downloaded 信号。您可以从蜘蛛中捕获它并从那里将时间及其差异分配给元。

      @classmethod
          def from_crawler(cls, crawler, *args, **kwargs):
              spider = super(SignalSpider, cls).from_crawler(crawler, *args, **kwargs)
              crawler.signals.connect(spider.item_scraped, signal=signals.item_scraped)
              return spider
      

      更详细的答案在here

      【讨论】:

        猜你喜欢
        • 2017-07-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多