可以通过javascript机械化支持ajax /填写表单吗?

时间:2015-07-26 00:37:44

标签: python ajax selenium mechanize mechanize-python

我正在尝试创建一个将在此网站上填写表单的程序: Insurance survey

我使用python 2.7并在经过3.4次尝试后机械化并实现机械化并不适用于3.4。我是一个新手,但在尝试这样做时学到了很多东西(python很棒)。

import mechanize
br = mechanize.Browser() 
urlofmypage = 'https://interactive.web.insurance.ca.gov/survey/'
br.open(urlofmypage) 
print br.geturl()
br.select_form(nr=0)

br['location'] = ['ALAMEDA BERKELEY']   #SET FORM ENTRIES
br['coverageType'] = ['HOMEOWNERS']
br['coverageAmount'] = ['$150,000']
br['homeAge'] = ['1-3 Years']

result = br.submit()
print result

这是我的错误:mechanize._form.ItemNotFoundError:名称不足的物品' $ 150,000'

问题是,只有在我填写表单字段location和coverageType之后,才会显示coverageAmount的选项:(。我一直在搞乱这个并在线观看大量视频,我所有的研究都带领了我得出结论,机械化不会做到这一点。

我还读到这是一个ajax电话,机械化不会为此工作。事情似乎指向selenium webdriver ...有人有任何意见吗?

3 个答案:

答案 0 :(得分:4)

AJAX调用由javascript执行,而mechanize无法运行javascript。 Mechanize仅查看静态HTML页面上的表单字段,并允许您填写&提交那些。这就是为什么你的研究指向Selenium或Ghost之类的东西,它们运行在可以执行javascript的真实浏览器之上。

虽然有一种更简单的方法可以做到这一点!如果您使用浏览器上的开发人员工具(例如Firefox或Chrome中的“网络”选项卡)并填写表单,即使使用AJAX,您也可以看到浏览器在幕后发出的请求:

Network tab in Firefox

这告诉你:

  • 浏览器发出了POST请求
  • 到此网址:https://interactive.web.insurance.ca.gov/survey/survey?type=homeownerSurvey&event=HOMEOWNERS
  • 使用以下表格参数:
    • 位置= ALAMEDA + ALAMEDA
    • coverageType =房主
    • coverageAmount = 150000
    • homeAge =新

您可以使用此信息在Python中发出相同的POST请求:

import urllib.parse, urllib.request

url = "https://interactive.web.insurance.ca.gov/survey/survey?type=homeownerSurvey&event=HOMEOWNERS"
data = urllib.parse.urlencode(dict(
    location="ALAMEDA ALAMEDA",
    coverageType="HOMEOWNERS",
    coverageAmount="150000",
    homeAge="New",
))
res = urllib.request.urlopen(URL, data.encode("utf8"))

print(res.read())

这是python3。 requests库为发出HTTP请求提供了更好的API。

修改:回答您的三个问题:

  

您创建的字典是否有可能拥有多个位置并使用for循环遍历它们?

是的,只需在代码周围添加一个循环,每次为location传递一个不同的值。我会将此代码放入一个函数中以使代码更清晰,如下所示:

https://gist.github.com/lost-theory/08786e3a27c8d8ce3839

  

结果是很多乱七八糟的,所以我必须找到一种方法来筛选它吧。喜欢挑出哪个

是的,乱码是HTML,您需要解析以收集您正在寻找的数据。查看python标准库中的HTMLParser,或安装类似lxmlBeautifulSoup的库,它们具有更好的API。您也可以尝试使用str.split手动解析文本。

如果您想将表格的行转换为python list,您需要查找所有行,如下所示:

  <tr Valign="top">
    <td align="left">Bankers Standard <a href='http://interactive.web.insurance.ca.gov/companyprofile/companyprofile?event=companyProfile&doFunction=getCompanyProfile&eid=5906'><small>(Info)</small></a></td>
    <td align="left"><div align="right">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;N/A</td>
    <td align="left"><div align="right">250</div></td>
    <td align="left">&nbsp;</td>
    <td align="left">Bankers Standard <a href='http://interactive.web.insurance.ca.gov/companyprofile/companyprofile?event=companyProfile&doFunction=getCompanyProfile&eid=5906'><small>(Info)</small></a></td>
    <td align="left"><div align="right">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1255</td>
    <td align="left"><div align="right">500</div></td>
  </tr>

您希望遍历所有<tr>(行)元素,抓取每行内的所有<td>(列)元素,然后清理每列中的文本(删除{{1}空格等。)。

关于如何在python中解析或抓取HTML的StackOverflow和教程有很多问题,如thisthis

  

你能解释为什么我们必须做data.encode行

当然!在documentation for urlopen中,它说:

  

数据必须是一个字节对象,指定要发送到服务器的其他数据,如果不需要这样的数据则为None。

&nbsp;函数返回一个unicode字符串,如果我们尝试将其传递给urlencode,我们会收到此错误:

urlopen

因此我们使用TypeError: POST data should be bytes or an iterable of bytes. It cannot be of type str. 将unicode字符串转换为字节。您通常需要使用字节来输入和输出。输出,如读取或写入磁盘上的文件,通过网络发送或接收数据,如HTTP请求等。This presentation可以很好地解释python中的字节与unicode字符串以及为什么需要解码/编码时做I / O.

答案 1 :(得分:0)

该页面没有进行AJAX调用。这是一个简单的Javascript代码,它是针对&#34;覆盖类型的onchange事件执行的:&#34;选择框。

如果您查看页面的来源,您会看到所有值都存储在Javascript函数coverageTypeOnChange()中。从那里你可以找出所有案例的帖子。如果这些值没有改变,您将能够在不运行Javascript代码的情况下自动抓取站点。

但是,如果值随着时间的推移而变化(例如通常作为保费),那么您最好不要选择Selenium或其他无头浏览器。

答案 2 :(得分:0)

这个问题让我头疼不已。关于以下内容:

br['location'] = ['ALAMEDA BERKELEY']   #SET FORM ENTRIES

这意味着您正在选择&#39; ALAMEDA BERKELEY&#39;从列表中。如果是,请尝试在项目后添加逗号:

br['location'] = ['ALAMEDA BERKELEY',]

否则使用:

br['location'] =  'ALAMEDA BERKELEY' 

我经常尝试针对机械化问题进行精心设计的解决方法,只回到原始代码并做一些修改......非常强大,非常无情