Python 非常奇怪的Web抓取问题:Post请求未按预期运行

Python 非常奇怪的Web抓取问题:Post请求未按预期运行,python,web-scraping,urllib2,mechanize,Python,Web Scraping,Urllib2,Mechanize,我试图以编程方式将一些数据提交到公司管理页面上的表单,而不是手工提交 我还写过很多其他工具,这些工具可以清理这个网站并处理数据。然而,出于某种原因,这件事给我带来了一大堆麻烦 使用浏览器浏览: 下面是我试图搜集和发布数据的页面。请注意,这些页面通常显示在js阴影框中,但是,如果禁用Javascript,它的功能会很好,因此我假设Javascript与scraper问题无关 (注意,由于这是一个公司页面,我已经填写了我已经用垃圾标题替换了所有的表单字段,因此,例如,客户号码完全是虚构的) 另外,由

我试图以编程方式将一些数据提交到公司管理页面上的表单,而不是手工提交

我还写过很多其他工具,这些工具可以清理这个网站并处理数据。然而,出于某种原因,这件事给我带来了一大堆麻烦

使用浏览器浏览: 下面是我试图搜集和发布数据的页面。请注意,这些页面通常显示在js阴影框中,但是,如果禁用Javascript,它的功能会很好,因此我假设Javascript与scraper问题无关

(注意,由于这是一个公司页面,我已经填写了我已经用垃圾标题替换了所有的表单字段,因此,例如,客户号码完全是虚构的)

另外,由于这是一个用户名/密码墙后面的公司页面,我不能提供网站进行测试,所以我尝试在这篇文章中尽可能多地注入细节

主要切入点如下:

在这个页面中,我单击“添加新表单”,这将在一个新标签中打开下一个页面(因为禁用了javascript)

在这个页面上,我填写小表单,单击submit,然后进入下一个页面,显示一条成功消息

应该很简单,对吗

代码尝试1:机械化 因此,正如您所看到的,我尝试复制在浏览器中执行的步骤。我加载初始的
/adm/forms
页面,按照第一个链接,即
添加表单
,填写表单,然后单击
提交
按钮。但这就是问题的症结所在。mechanize返回的响应与表单完全相同。没有错误消息,没有成功消息,当我手动检查我们的管理页面时,没有进行任何更改

检查网络活动 沮丧的是,我打开Chrome,看着网络标签,在浏览器中手动填写并提交表单

提交表格后,这是网络活动:

对我来说似乎很直截了当。css文件有
post
,然后是
get
,jquery库有另一个
get
。还有另一个
get
用于某种图像,但我不知道这是为了什么

检查POST请求的详细信息:

在谷歌搜索了一些关于抓取问题的信息后,我看到一个建议,服务器可能需要某个标题,我应该简单地复制POST请求中的所有内容,然后慢慢地删除标题,直到我知道哪一个是重要的。所以我就这么做了,复制了网络标签上的每一点信息,并坚持我的发帖请求

代码尝试2:Urllib 我在使用
Mechanize
时遇到了一些麻烦,所以我切换到了urllib2

import urllib
import urllib2
import base64 



url = 'www.our_company_page.com/adm/add_forms.php'
values = {
    'SID':'', #Hidden field
    'FormNumber':'FROM_PYTHON1030PM',
    'RevisionNumber':'5',
    'FormType':'H(num)',
    'fsubmit':'Save Page'
    }
username = 'USERNAME'
password = 'PASSWORD'

headers = { 
    'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Charset' : 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
    'Accept-Encoding' : 'gzip,deflate,sdch',
    'Accept-Language' : 'en-US,en;q=0.8',
    'User-Agent' :  'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)', 
    'Authorization': 'Basic %s' % base64.encodestring('%s:%s' % (username, password)),
    'Cache-Control' : 'max-age=0',
    'Connection' : 'keep-alive',
    'Content-Type' : 'application/x-www-form-urlencoded',
    'Cookie' : 'ID=201399',
    'Host' : 'our_company_page.com',
    'Origin' : 'http://our_company_page.com',
    'Referer' : 'http://our_company_page.com/adm/add_form.php',
    'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, ' 
            'like Gecko) Chrome/26.0.1410.43 Safari/537.31'
    }

data = urllib.urlencode(values)
req = urllib2.Request(url, data, headers)
response = urllib2.urlopen(req)
print response.read()
如您所见,我在
urllib2
中将Chrome的网络选项卡中的标题添加到POST请求中

Mechanize版本的另一个变化是,我现在通过向请求中添加相关cookie直接访问
add_form.php
页面

然而,即使尽我所能复制,我仍然有完全相同的问题:响应与我开始的页面完全相同--没有错误,没有成功消息,服务器上没有更改,只是返回到一个空白表单

最后一步:在绝望中,我安装WireShark 是时候做一些交通嗅探了。我决心在这个神奇的帖子请求中看到WTF的进展

我下载、安装并启动Wireshark。我过滤
http
,然后首先在浏览器中手动提交表单,然后运行代码并尝试以编程方式提交表单

这是网络流量:

浏览器:

蟒蛇:

除了标题的顺序稍有不同(这有关系吗),它们看起来完全一样

这就是我所处的位置,我完全不明白为什么一个与浏览器发出的请求几乎相同的
post
请求没有在服务器上进行任何更改

有人遇到过这样的事情吗?我错过了什么明显的东西吗?这是怎么回事


编辑 根据Ric的建议,我准确地复制了
POST
数据。我直接从Chrome的“网络源”选项卡复制它

修改后的代码如下所示

data = 'SegmentID=&Segment=FROMPYTHON&SegmentPosition=1&SegmentContains=Sections&fsubmit=Save+Page'
req = urllib2.Request(url, data, headers)
response = urllib2.urlopen(req)
print response.read()
我唯一更改的是
值,从
从浏览器
更改为
从Python

不幸的是,这仍然会产生相同的结果。回复是同一页,我从

更新
工作,但没有解决 我检查了
请求
库,使用它们的API复制了我的工作,然后神奇地工作了!这封信实际上通过了。问题仍然是:为什么!?我再次用wireshark拍摄了另一张快照,据我所知,这张快照与浏览器上的帖子完全相同

代码 Wireshark输出
请求

浏览器

所以,总结一下问题的现状。这是可行的,但我觉得没有什么真正的改变。我不知道为什么对Mechanize和urllib2的尝试都失败了。是什么使得
请求
帖子能够真正通过

编辑——王永堂建议: 在
Wing Tand Wongs
的建议下,我创建了一个cookie处理程序,并将其附加到
urlib.opener
。因此,不再在标头中手动发送更多cookie——事实上,我现在根本不分配任何内容

我首先连接到adm页面,其中包含指向表单的链接,而不是立即连接到表单

'http://my_web_page.com/adm/segments.php?&n=201399'
这将
ID
cookie提供给我的
urllib
cookieJar
。从这一点上,我跟随链接到该页面
def post(eventID, name, pos, containsID):

    segmentContains = ["Sections", "Products"]
    url = 'http://my_site.com/adm/add_page.php'
    cookies = dict(EventID=str(eventID))
    payload = { "SegmentID" : "",
                "FormNumber" : name,
                "RevisionNumber" : str(pos),
                "FormType" : containsID,
                "fsubmit" : "Save Page"
            }

    r = requests.post(
            url, 
            auth=(auth.username, auth.password),
            allow_redirects=True,
            cookies=cookies,
            data=payload) 
'http://my_web_page.com/adm/segments.php?&n=201399'
url = 'http://my_web_page.com/adm/segments.php?&n=201399'
post_url = 'http://my_web_page.com/adm/add_page.php'
values = {
    'SegmentID':'',
    'Segment':'FROM_PYTHON1030PM',
    'SegmentPosition':'5',
    'SegmentContains':'Products',
    'fsubmit':'Save Page'
    }
username = auth.username
password = auth.password

headers = { 
    'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Charset' : 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
    'Accept-Encoding' : 'gzip,deflate,sdch',
    'Accept-Language' : 'en-US,en;q=0.8',
    'User-Agent' :  'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)', 
    'Authorization': 'Basic %s' % base64.encodestring('%s:%s' % (username, password)),
    'Cache-Control' : 'max-age=0',
    'Connection' : 'keep-alive',
    'Content-Type' : 'application/x-www-form-urlencoded',
    'Host' : 'mt_site.com',
    'Origin' : 'http://my_site.com',
    'Referer' : 'http://my_site.com/adm/add_page.php',
    'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 Safari/537.31'
    }

COOKIEFILE = 'cookies.lwp'
cj = cookielib.LWPCookieJar()

if os.path.isfile(COOKIEFILE):
    cj.load(COOKIEFILE)

opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
urllib2.install_opener(opener)

data = urllib.urlencode(values)
req = urllib2.Request(url, headers=headers)
handle = urllib2.urlopen(req)

req = urllib2.Request(post_url, data, headers)
handle = urllib2.urlopen(req)

print handle.info()
print handle.read()
print
if cj:
    print 'These are the cookies we have received so far :'
    for index, cookie in enumerate(cj):
        print index, '  :  ', cookie
    cj.save(COOKIEFILE)
These are the cookies we have received so far :
<Cookie EventID=201399 for my_site.com/adm>  
password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
password_manager.add_password(None, gh_url, 'user', 'pass')

auth_manager = urllib2.HTTPBasicAuthHandler(password_manager)
opener = urllib2.build_opener(auth_manager)