我正在尝试屏幕抓取一个网页(使用 Mechanize),该网页以网格页面方式显示记录。我能够读取第一页中显示的值,但现在需要导航到下一页才能读取适当的值。
<tr>
<td><span>1</span></td>
<td><a href="javascript:__doPostBack('gvw_offices','Page$2')">2</a></td>
<td><a href="javascript:__doPostBack('gvw_offices','Page$3')" >3</a></td>
<td><a href="javascript:__doPostBack('gvw_offices','Page$4')" >4</a></td>
<td><a href="javascript:__doPostBack('gvw_offices','Page$5')" >5</a></td>
<td><a href="javascript:__doPostBack('gvw_offices','Page$6')">6</a></td>
<td><a href="javascript:__doPostBack('gvw_offices','Page$7')" >7</a></td>
<td><a href="javascript:__doPostBack('gvw_offices','Page$8')">8</a></td>
<td><a href="javascript:__doPostBack('gvw_offices','Page$9')" >9</a></td>
<td><a href="javascript:__doPostBack('gvw_offices','Page$10')" >10</a></td>
<td><a href="javascript:__doPostBack('gvw_offices','Page$11')">...</a></td>
</tr>
我能够访问所有链接,但是当我尝试这样做时:-
links = (row/"a")
links.each do |link|
agent.click link.attributes['href'] # This fails
agent.click link # This also fails
end
原因是agent.click需要URL作为参数。
有没有一种方法可以让我们在页面显示时读取所有值?如果不是的话,当 href 是回发而不是 URL 时,我们怎么能有这样的点击操作呢??
Mechanize 无法处理 javascript,所以基本上你有两个选择:
类似:
base_url = 'http://example.com/gvw_offcies&page='
links.each do |link|
page_number = ... #get the page number from link
agent.get base_url+page_number
end
上面的所有解决方案我在过去已经尝试过很长一段时间(尤其是 Celerity),但我的结论是它们都很糟糕并且有严重的缺点,这使得生活变得非常困难,因为它们基于相同的 HtmlUnit 引擎用于处理 Javascript。
Celerity 不是一个屏幕抓取工具,它缺乏 Windows 管理,并且基于 HTMLUNIT 引擎,该引擎根本不擅长处理 Javascript。然而,对于使用最低到中等水平的 Javascript 和 AJAX 请求的网站来说,它的工作速度很快。它基于 ruby,这对于那些不喜欢 Java 的人来说将是一种解脱。
最好的选择是使用 Selenium WebDriver API。这需要在您的 Linux 服务器上显示 X,并且它比 HtmlUnit 慢,但它不会因为使用任何派生或包装 HtmlUnit 时遇到的许多问题而困扰您。可以选择使用 HtmlUnit,但您会为了速度而牺牲准确性和一致性。 HtmlUnit 的抓取速度要快得多。
但是,对于抓取不属于您的其他网站来说,速度始终不是一件好事,因为它通常会导致 IP 禁令。
我个人的建议是远离任何使用 HtmlUnit 引擎的东西,并使用 Selenium,它可以直接远程控制您选择的浏览器,以获得最大的准确性和可靠性。
我会使用类似 webscarab 的东西来简单地查看 Javascript 所做的 POST 请求实际上去了哪里。特别是对于 AJAX 的东西,它们无论如何都只是 HTTP 请求。
只需启动它并将其设置为 Firefox 中的代理即可。大多数时候,您可以看到某种模式,然后直接抓取这些 URL
您可以尝试在 Jruby 中使用 Celerity 并将页面传递给 HTML 解析库。 Celerity 应该与 Watir 的 API 兼容,并且是 HtmlUnit 的包装器。 我使用 mechanize 进行数据收集,但对于一些用 JS 生成的网站不得不切换到这个。