【问题标题】:Python requests module not using post methodPython请求模块不使用post方法
【发布时间】:2015-07-02 14:04:13
【问题描述】:

我正在尝试将表单数据发布到 URL。我没有得到预期的响应,并对我从请求模块 (2.6.2) 获得的一些信息感到好奇。下面是post方法:

>>> response = requests.post(url, data={'uname':user, 'pwd':password,'phrase':'','submit':True})

如您所见,我使用的是post() 方法,所以我希望该方法是POSTdata 对象的键与表单元素的名称相匹配。 URL 是表单操作。

>>> vars(response.request)
{'method': 'GET', 'body': None, '_cookies': <<class 'requests.cookies.RequestsCookieJar'>[]>, 'headers': {'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'python-requests/2.6.2 CPython/3.3.6 Windows/8', 'Connection': 'keep-alive'}, 'hooks': {'response': []}, 'url': url}

response.request 属性应包含有关为此响应发送的请求的信息。这是method 属性是GET,我期望POST。 URL 看起来正确。如果表单发布,页面预计会返回其他内容,奇怪的是,我会检查请求标头。

>>> response.request.headers
{'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'python-requests/2.6.2 CPython/3.3.6 Windows/8', 'Connection': 'keep-alive'}
>>> 

那些看起来不错,但等一下!我的表单数据在哪里?为什么它没有随请求一起发送?我检查了历史记录,发现我被重定向了。这次我将allow_redirects=False 添加到我的post() 通话中。然后检查response.request 对象及其标头。

>>> vars(response.request)
{'method': 'POST', 'body': 'phrase=&pwd=****&uname=****&submit=True', '_cookies': <<class 'requests.cookies.RequestsCookieJar'>[]>, 'headers': {'Accept-Encoding': 'gzip, deflate', 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'python-requests/2.6.2 CPython/3.3.6 Windows/8', 'Content-Length': '56', 'Accept': '*/*', 'Connection': 'keep-alive'}, 'hooks': {'response': []}, 'url': 'http://myurl.com/path/to/script.php'}

这次是POST,所以这似乎是正确的。我觉得我在正确的轨道上。这很奇怪,body 属性看起来像一个查询字符串,不像我期望的表单帖子。

>>> response.request.headers
{'Accept-Encoding': 'gzip, deflate', 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'python-requests/2.6.2 CPython/3.3.6 Windows/8', 'Content-Length': '56', 'Accept': '*/*', 'Connection': 'keep-alive'}

那些标题,标题中同样没有表单数据。这是什么? 'Content-Type': 'application/x-www-form-urlencoded'?这就是我的表单数据看起来像查询字符串的原因吗?正常的内容类型是什么?它与 Chrome 访问相同 URL 报告的类型相同,所以我怀疑这是问题所在。

如果这一切看起来都没有,他们可能很聪明,会拒绝来自非本地来源的帖子,对吧?我主要担心的是表单数据是body 属性中的字符串,这似乎是错误的。如果没有,我可以聪明一点,设置 HTTP 标头来源吗?

【问题讨论】:

  • 我尝试用.post(headers={'origin':...,'host':..., ...}) 欺骗标题,但没有任何区别。

标签: python forms http python-requests python-3.3


【解决方案1】:
'application/x-www-form-urlencoded'

这是发布数据时的default content-type

是的,如果您的 POST 数据看起来像一个查询字符串,这没关系,这就是它使用x-www-form-urlencoded 发送的方式。从上一个链接:

控件名称/值按照它们在文档中出现的顺序列出。名称与值之间由= 分隔,名称/值对之间由&amp; 分隔。

下一步:

那些标题,标题中又没有表单数据

使用 POST,表单数据不会在标头中发送。它在请求的正文中发送。试试

>>> response.request.body
'uname=x&pwd=y&submit=True&phrase='

查看此数据

【讨论】:

  • 看来您是在说一切看起来都正确。也许我的问题是结果是保存了我在会话 cookie 中寻找的内容。我试图在post() 前面加上session = requests.session() 以捕捉这些内容。您是否建议更新问题以确定如何检索这些会话 cookie?
  • 当服务器希望客户端保存 cookie 时,将返回 HTTP Header Set-Cookie。您可以使用response.headers['set-cookie'] 捕获此 cookie 数据
  • 嗯,肯定有其他地方发生了什么事,因为我得到的响应是 302 重定向。如果凭据被接受,它将是一个不同的页面,但它会将我返回到表单 URL。我期待 set-cookie 标头,但没有得到它。我也没有收到有关不正确凭据的预期消息,因此它一定不会接受我的帖子数据。感谢您的回答,并认为它已经解决了我的问题,尽管我仍然遇到一个未知问题。
  • 如果您被 302 重定向到不正确的页面,我建议您使用谷歌浏览器访问该页面,并打开网络工具页面(ctrl+shift+j 然后单击“网络”选项卡)。在这里你会看到浏览器发送的确切的 POST 参数,你应该可以用 Python 模拟这个请求没有问题。
  • 你是对的,我被一个 GET 请求重定向。我的问题是,在 Chrome 上的重定向中,有一个 set-cookie 标头来存储 uname 和会话 cookie 中 pwd 值的突变。据我所知,我正在模仿所描述的请求。我在获取这些会话 cookie 时遇到了麻烦,但如果凭据得到验证,我也没有被重定向到我期望的位置。显然,是我做错了什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-21
相关资源
最近更新 更多