为什么cURL给出了正确的反应,但scrapy没有?

时间:2014-03-20 11:47:58

标签: python curl scrapy

为什么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中匹配,所以我不能将其视为问题。

2 个答案:

答案 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!