使用Python的机械化

时间:2015-06-29 18:13:21

标签: python asp.net forms web-scraping mechanize-python

编辑(10月30日):此帖子底部的解决方案。

大家好,

我是'web-scraping'场景的新手,并且一直在尝试使用Python从GISIS的页面中抓取数据。虽然我最初尝试使用requests执行此操作,但D8Amonk's post on SO将我引导至mechanize,这在大多数情况下效果非常好。

我能够通过添加kumar帖子中找到的标题来绕过我收到的初始403错误,但现在面临无法通过GISIS登录屏幕的问题其实际的相关网页。

Julian Todd在ScraperWiki的精彩帖子帮助我理解了如何禁用烦人的提交控件和处理页面的_doPostBack()机制。遗憾的是,登录页面仍然忽略了机械化程序完成表单提交的尝试 - 它无法识别已输入权限,用户名和密码。

我的代码段如下:

import os
import sys
import webbrowser
import mechanize
import urllib2
import cookielib
from bs4 import BeautifulSoup

header = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
       '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': 'none',
       'Accept-Language': 'en-US,en;q=0.8',
       'Connection': 'keep-alive'}
request = urllib2.Request('https://gisis.imo.org/Public/SHIPS/Default.aspx', None, header)

...

jar = cookielib.CookieJar()
browser = mechanize.Browser()
browser.set_cookiejar(jar)
browser.set_handle_robots(False)

browser.open(request)
browser.select_form(nr=0)
browser.form.set_all_readonly(False)
browser.form['ctl00$cpMain$ddlAuthorityType'] = ['PUBLIC']
browser.form['ctl00$cpMain$txtUsername'] = username
browser.form['ctl00$cpMain$txtPassword'] = password
browser.find_control('ctl00$cpMain$cbxRemember').selected = False
browser.find_control('ctl00$cpMain$btnRegister').disabled = True
browser["__EVENTTARGET"] = "lnkNext"
browser["__EVENTARGUMENT"] = ""
resp = browser.submit()
print '-- Request Made Successfully --'
return resp.read()
然后将

resp.read()写入.HTML文件并在Firefox中打开。对browser.form[...]行进行评论和取消注释会产生一个有趣的发现:如果 Authority (在本例中为“Public”)包含在表单提交中,那么该网页将识别权威,但抱怨必须输入用户名和密码。

但是,如果权限行被注释掉,那么生成的网页将识别出已输入用户名和密码,但会要求选择权限(在这种情况下,将填写用户名字段)正确,但密码字段将为空;我不确定这是否是理想或预期的行为)。同样,只要权限行仍然被注释掉,那么我可以在我的代码中注释掉用户名或密码行,结果网页将要求权限无论其他字段是什么注释掉(即如果我只提交密码,那么该页面将要求提供权限和用户名)。

是否有人对我可能做错了什么或者在哪里看?这似乎是一个相当不寻常的问题 - 在Google上搜索未能产生任何其他人经历过的类似问题。

P.S。这是我在StackOverflow上的第一篇文章。我试图附加图像来解释我所描述的场景,但显然缺少发布图像所需的代表。如果我过于冗长或做错了什么,即格式化我的帖子,我会大声道歉 - 请纠正我!!

编辑(10月30日):在转向其他事情并找到解决方案后回到这个项目。解决方案如下:

这实际上没有像我想象的那样复杂。修改__EVENTTARGET__EVENTARGUMENT是不必要的。相反,__VIEWSTATE__VIEWSTATEGENERATOR都需要修改。通过检查Firebug中成功的POST请求,找到了正确的使用值。示例代码如下:

browser.form['__VIEWSTATE'] = 'blablabla'
browser.form['__VIEWSTATEGENERATOR'] = 'blablabla'

成功修改这两个值会将我登录到主页面。我希望这有助于某人!

1 个答案:

答案 0 :(得分:0)

感谢您提示使用Firebug(或Chrome的内置开发人员工具)来检查请求内容,并查看哪些表单字段实际发布回服务器。我不得不添加一个额外的字段{'SubmitLogin':'Sign In'}来让我的服务器进行身份验证。