mechanize 可以支持 ajax / 通过 javascript 填写表格吗?
Can mechanize support ajax / filling out forms via javascript?
我正在尝试创建一个程序来填写此网站上的表格:
Insurance survey
我正在使用 python 2.7 并在多次尝试 3.4 后使用 mechanize 并意识到 mechanize 不适用于 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'] = ['0,000']
br['homeAge'] = ['1-3 Years']
result = br.submit()
print result
这是我的错误:mechanize._form.ItemNotFoundError:名称为“$150,000”的商品不足
问题是,只有在我填写了表格字段 location 和 coverageType 之后,coverageAmount 选项才会显示 :( 。我一直在搞这个,在线观看了很多视频,我所有的研究都导致了我的结论是 mechanize 不会这样做。
我还了解到这是一个 ajax 调用,而 mechanize 对此不起作用。事情似乎指向 selenium webdriver ...有人有任何意见吗?
AJAX调用由javascript执行,mechanize没办法运行javascript。 Mechanize 仅查看静态 HTML 页面上的表单字段,并允许您填写并提交这些字段。这就是为什么您的研究将您指向诸如 Selenium 或 Ghost 之类的东西,后者 运行 在可以执行 javascript.
的真实浏览器之上
虽然有一种更简单的方法可以做到这一点!如果您使用浏览器上的开发人员工具(例如 Firefox 或 Chrome 中的网络选项卡)并填写表单,您可以看到您的浏览器在后台发出的请求,即使是 AJAX:
这告诉你:
- 浏览器发出了
POST
请求
- 为此URL:
https://interactive.web.insurance.ca.gov/survey/survey?type=homeownerSurvey&event=HOMEOWNERS
- 使用以下表单参数:
- 位置=阿拉米达+阿拉米达
- coverageType=HOMEOWNERS
- 覆盖金额=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。
编辑: 回答你的三个问题:
is it possible for the dictionary that you've created to have more than 1 location and cycle through them using a for loop?
是的,只需在代码周围添加一个循环并每次为 location
传递不同的值。我会将这段代码放入一个函数中以使代码更清晰,如下所示:
https://gist.github.com/lost-theory/08786e3a27c8d8ce3839
the results are in a lot of jibberish, so I'd have to find a way to sift through it huh. Like pick out which is which
是的,乱码是 HTML,您需要对其进行解析以收集您要查找的数据。看看 HTMLParser in the python standard library, or install a library like lxml or BeautifulSoup,它有更好的 API。您也可以尝试使用 str.split
.
手动解析文本
如果您想将 table 的行转换为 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>
(列)元素,然后清理每列中的文本(删除那些
空格等)。
关于如何在 python 中解析或抓取 HTML 的 Whosebug 和 Internet 上的教程有很多问题,例如 this or this。
could you explain why we had to do the data.encode line
好的!在 documentation for urlopen
中,它表示:
data must be a bytes object specifying additional data to be sent to the server, or None if no such data is needed.
urlencode
函数 returns 一个 unicode 字符串,如果我们试图将其传递给 urlopen
,我们会得到这个错误:
TypeError: POST data should be bytes or an iterable of bytes. It cannot be of type str.
所以我们使用data.encode('utf8')
将unicode字符串转换为字节。您通常需要使用字节进行输入和输出,例如读取或写入磁盘上的文件、通过网络发送或接收数据(例如 HTTP 请求等)。This presentation 对 [ 中的字节与 unicode 字符串有很好的解释=97=] 以及为什么在执行 I/O.
时需要 decode/encode
该页面没有 AJAX 调用。这是从 onchange
事件为 "Type of Coverage:" select 框执行的简单 Javascript 代码。
如果您查看页面的源代码,您会发现所有值都存储在 Javascript 函数 coverageTypeOnChange()
中。从中你可以计算出所有情况下 post 的内容。如果这些值没有改变,您将能够在没有 运行 Javascript 代码的情况下自动抓取网站。
但是,如果值随时间变化(例如,保费通常会发生变化),那么您最好还是看看 Selenium 或替代的无头浏览器。
这个问题曾经让我很头疼。关于以下行:
br['location'] = ['ALAMEDA BERKELEY'] #SET FORM ENTRIES
这意味着您正在从列表中选择 'ALAMEDA BERKELEY'。如果是,则尝试在项目后添加一个逗号:
br['location'] = ['ALAMEDA BERKELEY',]
否则使用:
br['location'] = 'ALAMEDA BERKELEY'
我经常为机械化问题尝试精心设计的解决方法,只是回到我的原始代码并稍作修改......非常强大,非常无情
我正在尝试创建一个程序来填写此网站上的表格: Insurance survey
我正在使用 python 2.7 并在多次尝试 3.4 后使用 mechanize 并意识到 mechanize 不适用于 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'] = ['0,000']
br['homeAge'] = ['1-3 Years']
result = br.submit()
print result
这是我的错误:mechanize._form.ItemNotFoundError:名称为“$150,000”的商品不足
问题是,只有在我填写了表格字段 location 和 coverageType 之后,coverageAmount 选项才会显示 :( 。我一直在搞这个,在线观看了很多视频,我所有的研究都导致了我的结论是 mechanize 不会这样做。
我还了解到这是一个 ajax 调用,而 mechanize 对此不起作用。事情似乎指向 selenium webdriver ...有人有任何意见吗?
AJAX调用由javascript执行,mechanize没办法运行javascript。 Mechanize 仅查看静态 HTML 页面上的表单字段,并允许您填写并提交这些字段。这就是为什么您的研究将您指向诸如 Selenium 或 Ghost 之类的东西,后者 运行 在可以执行 javascript.
的真实浏览器之上虽然有一种更简单的方法可以做到这一点!如果您使用浏览器上的开发人员工具(例如 Firefox 或 Chrome 中的网络选项卡)并填写表单,您可以看到您的浏览器在后台发出的请求,即使是 AJAX:
这告诉你:
- 浏览器发出了
POST
请求 - 为此URL:
https://interactive.web.insurance.ca.gov/survey/survey?type=homeownerSurvey&event=HOMEOWNERS
- 使用以下表单参数:
- 位置=阿拉米达+阿拉米达
- coverageType=HOMEOWNERS
- 覆盖金额=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。
编辑: 回答你的三个问题:
is it possible for the dictionary that you've created to have more than 1 location and cycle through them using a for loop?
是的,只需在代码周围添加一个循环并每次为 location
传递不同的值。我会将这段代码放入一个函数中以使代码更清晰,如下所示:
https://gist.github.com/lost-theory/08786e3a27c8d8ce3839
the results are in a lot of jibberish, so I'd have to find a way to sift through it huh. Like pick out which is which
是的,乱码是 HTML,您需要对其进行解析以收集您要查找的数据。看看 HTMLParser in the python standard library, or install a library like lxml or BeautifulSoup,它有更好的 API。您也可以尝试使用 str.split
.
如果您想将 table 的行转换为 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>
(列)元素,然后清理每列中的文本(删除那些
空格等)。
关于如何在 python 中解析或抓取 HTML 的 Whosebug 和 Internet 上的教程有很多问题,例如 this or this。
could you explain why we had to do the data.encode line
好的!在 documentation for urlopen
中,它表示:
data must be a bytes object specifying additional data to be sent to the server, or None if no such data is needed.
urlencode
函数 returns 一个 unicode 字符串,如果我们试图将其传递给 urlopen
,我们会得到这个错误:
TypeError: POST data should be bytes or an iterable of bytes. It cannot be of type str.
所以我们使用data.encode('utf8')
将unicode字符串转换为字节。您通常需要使用字节进行输入和输出,例如读取或写入磁盘上的文件、通过网络发送或接收数据(例如 HTTP 请求等)。This presentation 对 [ 中的字节与 unicode 字符串有很好的解释=97=] 以及为什么在执行 I/O.
该页面没有 AJAX 调用。这是从 onchange
事件为 "Type of Coverage:" select 框执行的简单 Javascript 代码。
如果您查看页面的源代码,您会发现所有值都存储在 Javascript 函数 coverageTypeOnChange()
中。从中你可以计算出所有情况下 post 的内容。如果这些值没有改变,您将能够在没有 运行 Javascript 代码的情况下自动抓取网站。
但是,如果值随时间变化(例如,保费通常会发生变化),那么您最好还是看看 Selenium 或替代的无头浏览器。
这个问题曾经让我很头疼。关于以下行:
br['location'] = ['ALAMEDA BERKELEY'] #SET FORM ENTRIES
这意味着您正在从列表中选择 'ALAMEDA BERKELEY'。如果是,则尝试在项目后添加一个逗号:
br['location'] = ['ALAMEDA BERKELEY',]
否则使用:
br['location'] = 'ALAMEDA BERKELEY'
我经常为机械化问题尝试精心设计的解决方法,只是回到我的原始代码并稍作修改......非常强大,非常无情