为什么cURL会给出正确的答案,但scrapy不会?
我希望使用javascript填写表单以填写表单,然后发布并在提供内容之前进行验证。
在初始GET请求中从javascript中抓取参数后,我在python中复制了这个js。我的“TS644333_75”的值与js值相匹配(通过执行document.write(..)out来测试,而不是让它像正常一样提交),如果你将结果复制并粘贴到cURL也有效。例如:
curl --http1.0 'http://www.betvictor.com/sports/en/football' -H 'Connection: keep-alive'
-H 'Accept-Encoding: gzip,deflate' -H 'Accept-Language: en'
-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
-H 'Referer: http://www.betvictor.com/sports/en/football' -H 'User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0'
--data
'TS644333_id=3&
TS644333_75=286800b2a80cd3334cd2895e42e67031%3Ayxxy%3A3N6QfX3q%3A1685704694&
TS644333_md=1&
TS644333_rf=0&
TS644333_ct=0&
TS644333_pd=0' --compressed
从哪里获得 TS644333_75 我只需复制并粘贴模拟js时计算出的python代码的结果。
在wireshark中监控数据包显示此POST如here所示(我添加了一些行空格以使POST数据更具可读性,但除此之外就像在wireshark中看到的那样)。
但是,如果我开始使用scrapy shell:
1) scrapy shell "http://www.betvictor.com/sports/en/football"
并构建表单请求:
2) from scrapy.http import FormRequest
req=FormRequest(
url='http://www.betvictor.com/sports/en/football',
formdata={
'TS644333_id': '3',
'TS644333_75': '286800b2a80cd3334cd2895e42e67031:yxxy:3N6QfX3q:1685704694',
'TS644333_md': '1',
'TS644333_rf': '0',
'TS644333_ct': '0',
'TS644333_pd': '0'
},
headers={
'Referer': 'http://www.betvictor.com/sports/en/football',
'Connection': 'keep-alive'
}
)
然后获取它
3) fetch(req)
我回复的响应主体只是另一个javascript挑战,而不是所需的提供内容。
然而,在wireshark中看到的数据包(同样在POST参数中提供了一些新的可读性) 显示here,我的眼睛看起来缩进
出了什么问题?如何看起来相同的数据包导致不同的服务器响应?为什么这不适用于scrapy?
它可能是我在POST时计算的参数中的“:”的编码,但它看起来已经被正确编码,并且两者都在wireshark中匹配,所以我不能将其视为问题。
答案 0 :(得分:4)
如果您在网址上附加斜杠似乎也有效 - 所以scrapy请求相同,但网址已更改为:
http://www.betvictor.com/sports/en/football/
答案 1 :(得分:2)
事实证明,这个服务器的参数顺序真的很重要(我猜是因为它模拟了一个带有序输入的隐藏表格,这是一个额外的验证检查)。在python请求中使用POST str和url编码手工(即':' --> '%3A'
)使事情有效。因此虽然wireshark数据包足够相同,但它们不同的唯一方法是参数字符串顺序,实际上这是关键。
在Scrapy
传递一个元组,如:
ot= ( ('TS644333_id', '3'),
('TS644333_75', value),
('TS644333_md', '1'),
('TS644333_rf', '0'),
('TS644333_ct', '0'),
('TS644333_pd', '0')
)
到formdata=
而不是字典,这样订单也可以保存。
标题{'Content-Type': 'application/x-www-form-urlencoded'}
也是必需的。
正如anana
在他的回答中所提到的那样,附上一个尾随的' /'所有请求URL也修复了事情,实际上你可以单独使用GET请求,没有js模拟,如果你这样做就没有表格POST!