我使用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网站获得任何回复。
通过提出相同的请求但没有Connection: close
标题对fiddler进行测试后,我得到了正确的响应。现在的问题是如何删除Connection: close
标题?
答案 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 answer和this doc。我想也许该网站正在重定向设置cookie的请求,但事实并非如此。所以修复它应该是一个相对简单的问题。
答案 3 :(得分:1)
使用您的代码,第一个连接对我来说很合适 - 它使用您提供的标头并获得正确的响应。我修改了您的PG.connect(ENV['DATABASE_URL'])
方法,以关注产品链接,并从收到的网页中打印parse
标记的内容,这也很好。下面的示例日志和打印输出。我怀疑你因为请求过多而放慢了速度。
<title>
答案 4 :(得分:1)
您可以使用此工具https://curl.trillworks.com/