Python:如何只使用原始字符串发送POST请求

3
我想使用原始字符串发送POST请求。
我正在编写一个解析器。我加载了页面并在Firebug中看到了一个包含许多头部和主体的复杂请求:
__EVENTTARGET=&__EVENTARGUMENT=&__VIEW.... (11Kb or unreadable text)

我该如何手动发送这个精确请求(包括头文件和POST正文),并将其作为一个大字符串传递?
例如:
func("%(headers) \n \n %(body)" % ... )

我希望它能够通过我的脚本发送(并处理响应),而不想手动创建参数和标头的字典。
谢谢。

你怎么知道头部是什么,正文是什么? - Burhan Khalid
@BurhanKhalid,我从Firebug中复制了它。我将解析响应。 - Ben Usman
我不理解你试图实现的过程细节。你是在问如何仅使用Python中的原始字符串发送POST请求吗?当你谈论Firebug时,它开始让我感到困惑,好像有些客户端操作你想要做。 - jdi
@jdi,是的,只是使用Python中的原始字符串进行请求。谢谢你的措辞。 - Ben Usman
1
你可能别无选择,只能将头文件转换为字典格式,以便将其添加到请求中。 - jdi
2个回答

7

另一个回答变得太大和混乱了,并且展示了更多的内容。我觉得应该为将来的读者包括一个更简洁的答案:

import urllib2
import urllib
import urlparse

# this was the header and data strings you already had
headers = 'baz=3&foo=1&bar=2'
data = 'baz=3&foo=1&bar=2'

header_dict = dict(urlparse.parse_qsl(headers))

r = urllib2.Request('http://www.foo.com', data, headers)
resp = urllib2.urlopen(r)

您需要至少将标题解析为字典,但这是最小的工作。然后将其全部传递给新请求即可。
*注意:此简明示例假设您的标头和数据正文均为application/x-www-form-urlencoded格式。如果标题以原始字符串格式出现,例如Key: Value,请参见其他答案以获取有关首先解析其的更多详细信息。
最终,您不能只复制并粘贴原始文本并运行新请求。它必须按正确格式分成标题和数据。

urllib2.HTTPError: HTTP错误400:错误请求,这是由于在查询“Название аукциона”= Ford时,页面生成了疯狂的请求。你有任何想法为什么会出现这种情况吗? - Ben Usman
你是否已经将头部和主体分开,并且它们都是 application/x-www-form-urlencoded 类型的? - jdi
我的请求主体之前是错误的,现在已经修复了。但有时服务器会以错误的编码方式响应(我只能看到输出中的垃圾字符),尽管头信息是 'Accept-Charset': 'utf-8;q=0.7,*;q=0.3'。不管怎样,谢谢。 - Ben Usman

2
import urllib
import urllib2

# DATA:

# option #1 - using a dictionary
values = {'name': 'Michael Foord', 'location': 'Northampton', 'language': 'Python' }
data = urllib.urlencode(values)

# option #2 - directly as a string
data = 'name=Michael+Foord&language=Python&location=Northampton'

# HEADERS:

# option #1 - convert a bulk of headers to a dictionary (really, don't do this)    

headers = '''
Host: www.http.header.free.fr
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
Accept-Language: Fr
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0)
Connection: Keep-Alive
'''

headers = dict([[field.strip() for field in pair.split(':', 1)] for pair in headers.strip().split('\n')])

# option #2 - just use a dictionary

headers = {'Accept': 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,',
           'Accept-Encoding': 'gzip, deflate',
           'Accept-Language': 'Fr',
           'Connection': 'Keep-Alive',
           'Host': 'www.http.header.free.fr',
           'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0)'}

# send the request and receive the response

req = urllib2.Request('http://www.someserver.com/cgi-bin/register.cgi', data, headers)
response = urllib2.urlopen(req)
the_page = response.read()

似乎即使没有标题也可以工作,但最好将它们转换为字典。谢谢,@jdi。 - Ben Usman
@MInner:urlparse.parse_qsl(headers) - jdi
您的标头示例假设OP已经有了词典。也许可以从我的urlparse建议开始,只需将其传递给标头值,而无需进行所有这些大型标头解析操作。 - jdi
在帖子中添加了标题。您应该将标题作为字典传递。另一种选择是将它们转换为字典,或者使用套接字并自己实现HTTP协议的一部分。我不认为这是您想要的。 - someone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接