Scrapy错误:用户超时导致连接失败

时间:2018-01-25 11:03:30

标签: python scrapy twisted

我使用scrapy刮刮adidas网站:http://www.adidas.com/us/men-shoes。 但它总是显示错误:

  

用户超时导致连接失败:获取http://www.adidas.com/us/men-shoes的时间超过180.0秒..

重试5次然后完全失败。

我可以访问chrome上的url,但它没有使用scrapy 我尝试过使用自定义用户代理并模拟标头请求,但它仍然无效。

以下是我的代码:

import scrapy


class AdidasSpider(scrapy.Spider):
    name = "adidas"

    def start_requests(self):

        urls = ['http://www.adidas.com/us/men-shoes']

        headers = {
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
            "Accept-Encoding": "gzip, deflate",
            "Accept-Language": "en-US,en;q=0.9",
            "Cache-Control": "max-age=0",
            "Connection": "keep-alive",
            "Host": "www.adidas.com",
            "Upgrade-Insecure-Requests": "1",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
        }

        for url in urls:
            yield scrapy.Request(url, self.parse, headers=headers)

    def parse(self, response):
        yield(response.body)

Scrapy日志:

{'downloader/exception_count': 1,
 'downloader/exception_type_count/twisted.web._newclient.ResponseNeverReceived': 1,
 'downloader/request_bytes': 224,
 'downloader/request_count': 1,
 'downloader/request_method_count/GET': 1,
 'finish_reason': 'shutdown',
 'finish_time': datetime.datetime(2018, 1, 25, 10, 59, 35, 57000),
 'log_count/DEBUG': 2,
 'log_count/INFO': 9,
 'retry/count': 1,
 'retry/reason_count/twisted.web._newclient.ResponseNeverReceived': 1,
 'scheduler/dequeued': 1,
 'scheduler/dequeued/memory': 1,
 'scheduler/enqueued': 2,
 'scheduler/enqueued/memory': 2,
 'start_time': datetime.datetime(2018, 1, 25, 10, 58, 39, 550000)}

更新

在使用fiddler查看请求标头并进行一些测试后,我发现了导致问题的原因。 Scrapy默认发送Connection: close标头,因此我没有从adidas网站获得任何回复。

enter image description here

通过提出相同的请求但没有Connection: close标题对fiddler进行测试后,我得到了正确的响应。现在的问题是如何删除Connection: close标题?

enter image description here

5 个答案:

答案 0 :(得分:3)

由于scrapy不允许您编辑Connection: close标题。我使用scrapy-splash代替使用splash发出请求。

现在可以覆盖Connection: close标题,现在每个人都可以使用。不利的一面是,现在网页必须加载所有资产才能从启动获得响应,速度较慢但有效。

Scrapy应添加选项以编辑其默认的Connection: close标头。它在库中是硬编码的,不能轻易覆盖。

以下是我的工作代码:

headers = {
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.9",
        "Host": "www.adidas.com",
        "Connection": "keep-alive",
        "Upgrade-Insecure-Requests": "1",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
    }

    def start_requests(self):
        url = "http://www.adidas.com/us/men-shoes?sz=120&start=0"
        yield SplashRequest(url, self.parse, headers=self.headers)

答案 1 :(得分:2)

好吧,至少你应该使用你写的标题添加' headers = headers'你的scrapy.Request。但是,即使在我试图产生scrapy后,它仍然无法工作。请求(url,self.parse,headers = headers)

接下来,我将settings.py中的User-Agent更改为标题中的一个,即" Mozilla / 5.0(Windows NT 10.0; Win64; x64)AppleWebKit / 537.36(KHTML,类似Gecko)Chrome / 63.0.3239.132 Safari / 537.36" 并且没有使用你在scrapy中写过的标题。它有效。

标题可能有问题。但我很确定它不是关于cookie的。

答案 2 :(得分:1)

我尝试使用curl访问该网站,并且连接挂起。

curl -v -L http://www.adidas.com/us/men-shoes

所以我跳进了浏览器的调试器,注意到请求中有一个Cookie标头。然后我从标题中复制了整个值并将其粘贴到curl --headers命令中。

curl -v -L -H 'Cookie:<cookie value here>' http://www.adidas.com/us/men-shoes

现在HTML内容返回。因此,该网站在某些时候设置了访问网站其余部分所需的cookie。不幸的是,我不确定以何种方式或如何以编程方式获取cookie。如果你搞清楚了,请告诉我们。希望这会有所帮助。

更新

看起来有一些方法可以在Scrapy中使用持久性会话数据(即cookie)(我从来没有使用它直到这一点:))。请查看this answerthis doc。我想也许该网站正在重定向设置cookie的请求,但事实并非如此。所以修复它应该是一个相对简单的问题。

答案 3 :(得分:1)

使用您的代码,第一个连接对我来说很合适 - 它使用您提供的标头并获得正确的响应。我修改了您的PG.connect(ENV['DATABASE_URL'])方法,以关注产品链接,并从收到的网页中打印parse标记的内容,这也很好。下面的示例日志和打印输出。我怀疑你因为请求过多而放慢了速度。

<title>

答案 4 :(得分:1)

您可以使用此工具https://curl.trillworks.com/

  • 从Chrome获取curl命令
  • 运行已转换的python代码(我通过请求从您的URL获得了响应200)
  • 复制scrapy.Request的标题和Cookie