Python 2& 3:urllib&请求POST数据神秘地消失

时间:2014-02-23 04:37:45

标签: python post urllib2 form-submit python-requests

我正在使用Python从许多具有简单HTML输入表单的网页中抓取数据,例如本页底部的“用户名:”表单:

http://www.w3schools.com/html/html_forms.asp(这只是一个简单的例子来说明问题)

Firefox Inspect Element表示此表单字段具有以下HTML结构:

<form name="input0" target="_blank" action="html_form_action.asp" method="get">
Username: 
<input name="user" size="20" type="text"></input>
<input value="Submit" type="submit"></input>
</form>

我想要做的就是填写此表单并获取结果页面:

http://www.w3schools.com/html/html_form_action.asp?user=ThisIsMyUserName

通过在“用户名”字段中输入“ThisIsMyUserName”并按“提交”,我的浏览器会生成这些内容。但是,我尝试的每个方法(详情如下)都会返回包含未更改形式的原始页面的内容,而没有任何迹象表明我提交的表单数据已被识别,即我从上面的第一个链接获取内容以响应我的请求,当我希望收到第二个链接的内容时。

我怀疑问题与上面表格中的action="html_form_action.asp"有关,或者是某些我遗漏的隐藏字段(我不知道该寻找什么 - 我是新来的表单提交)。有什么建议吗?

这是我为此所做的事情:


在Python 3中使用urllib.requests:

import urllib.request 
import urllib.parse

# Create dict of form values
example_data = urllib.parse.urlencode({'user': 'ThisIsMyUserName'})

# Encode dict
example_data = example_data.encode('utf-8')

# Create request
example_url = 'http://www.w3schools.com/html/html_forms.asp'
request = urllib.request.Request(example_url, data=example_data) 

# Create opener and install
my_url_opener = urllib.request.build_opener() # no handlers
urllib.request.install_opener(my_url_opener)

# Open the page and read content
web_page = urllib.request.urlopen(request)
content = web_page.read()

# Save content to file
my_html_file = open('my_html_file.html', 'wb')
my_html_file.write(content)

但是返回给我并保存在'my_html_file.html'中的内容是包含的原始页面 没有任何迹象表明我的表格数据被识别的未经改动的表格,即我得到这个页面作为回应:qqqhttp://www.w3schools.com/html/html_forms.asp

...如果我没有提出这个要求,那就是我所期望的 数据参数(可以将请求从POST更改为GET)。

当然,我做的第一件事就是检查我的请求是否正确构建:

# Just double-checking the request is set up correctly
print("GET or POST?", request.get_method())
print("DATA:", request.data)
print("HEADERS:", request.header_items())

产生以下输出:

GET或POST? POST

DATA:b'user = ThisIsMyUserName'

HEADERS:[('Content-length','21'),('Content-type','application / x-www-form-urlencoded'),('User-agent','Python-urllib / 3.3'),('主持人','www.w3schools.com')]

所以看来POST请求的结构是正确的。重新阅读之后 我没有文档,也没有成功地在网上搜索这个问题的答案 转到另一个工具:请求模块。我试图执行相同的任务:

import requests

example_url = 'http://www.w3schools.com/html/html_forms.asp'
data_to_send = {'user': 'ThisIsMyUserName'}
response = requests.post(example_url, params=data_to_send)
contents = response.content

我得到了同样的结果。在这一点上,我想也许这是一个Python 3 问题。所以我启动了我可靠的Python 2.7并尝试以下方法:

import urllib, urllib2

data = urllib.urlencode({'user' : 'ThisIsMyUserName'})
resp = urllib2.urlopen('http://www.w3schools.com/html/html_forms.asp', data)
content = resp.read()

我又得到了同样的结果!为了彻底,我想我会尝试实现 将字典值编码到url并尝试GET请求的结果相同:

# Using Python 3

# Construct the url for the GET request
example_url = 'http://www.w3schools.com/html/html_forms.asp'
form_values = {'user': 'ThisIsMyUserName'}
example_data = urllib.parse.urlencode(form_values)
final_url = example_url + '?' + example_data
print(final_url)

这会为final_url吐出以下值:

qqqhttp://www.w3schools.com/html/html_forms.asp用户= ThisIsMyUserName

我将它插入我的浏览器,我看到这个页面完全相同 原始页面,这正是我的程序正在下载的内容。

我还尝试添加额外的标头和Cookie支持无济于事。

我已经尝试了我能想到的一切。知道会出现什么问题吗?

1 个答案:

答案 0 :(得分:3)

表格陈述行动和方法;你忽略了两者。该方法声明表单使用的是GET,而不是POST,操作会告诉您将表单数据发送到html_form_action.asp

action属性的行为与HTML页面中的任何其他URL说明符相同;除非它以方案开头(因此使用http://...https://...等),它相对于页面的当前基本URL。

GET HTTP方法将带网址编码的表单参数添加到目标网址,并带有问号:

import urllib.request 
import urllib.parse

# Create dict of form values
example_data = urllib.parse.urlencode({'user': 'ThisIsMyUserName'})

# Create request
example_url = 'http://www.w3schools.com/html/html_form_action.asp'
get_url = example_url + '?' + example_data

# Open the page and read content
web_page = urllib.request.urlopen(get_url)
print(web_page.read().decode(web_page.info().get_param('charset', 'utf8')))

或使用requests

import requests

example_url = 'http://www.w3schools.com/html/html_form_action.asp'
data_to_send = {'user': 'ThisIsMyUserName'}
response = requests.get(example_url, params=data_to_send)
contents = response.text
print(contents)

在这两个示例中,我还解码了对Unicode文本的响应(使用requests属性,response.text使{{1}}更容易。