我正在尝试创建一个将在此网站上填写表单的程序: 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 ...有人有任何意见吗?
答案 0 :(得分:4)
AJAX调用由javascript执行,而mechanize无法运行javascript。 Mechanize仅查看静态HTML页面上的表单字段,并允许您填写&提交那些。这就是为什么你的研究指向Selenium或Ghost之类的东西,它们运行在可以执行javascript的真实浏览器之上。
虽然有一种更简单的方法可以做到这一点!如果您使用浏览器上的开发人员工具(例如Firefox或Chrome中的“网络”选项卡)并填写表单,即使使用AJAX,您也可以看到浏览器在幕后发出的请求:
这告诉你:
POST
请求https://interactive.web.insurance.ca.gov/survey/survey?type=homeownerSurvey&event=HOMEOWNERS
您可以使用此信息在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,或安装类似lxml或BeautifulSoup的库,它们具有更好的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"> N/A</td>
<td align="left"><div align="right">250</div></td>
<td align="left"> </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"> 1255</td>
<td align="left"><div align="right">500</div></td>
</tr>
您希望遍历所有<tr>
(行)元素,抓取每行内的所有<td>
(列)元素,然后清理每列中的文本(删除{{1}空格等。)。
关于如何在python中解析或抓取HTML的StackOverflow和教程有很多问题,如this或this。
你能解释为什么我们必须做data.encode行
当然!在documentation for urlopen
中,它说:
数据必须是一个字节对象,指定要发送到服务器的其他数据,如果不需要这样的数据则为None。
函数返回一个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'
我经常尝试针对机械化问题进行精心设计的解决方法,只回到原始代码并做一些修改......非常强大,非常无情