我有一个使用 Selenium 库用 Java 开发的页面爬虫。爬网程序会浏览一个通过 Javascript 3 应用程序启动的网站,这些应用程序在弹出窗口中显示为 HTML。
爬网程序在启动其中 2 个应用程序时没有出现任何问题,但在启动第 3 个应用程序时,爬网程序将永远卡住。
我使用的代码类似于
public void applicationSelect() {
...
//obtain url by parsing tag href attributed
...
this.driver = new HtmlUnitDriver(BrowserVersion.INTERNET_EXPLORER_8);
this.driver.seJavascriptEnabled(true);
this.driver.get(url); //the code does not execute after this point for the 3rd app
...
}
我还尝试通过以下代码单击网络元素
public void applicationSelect() {
...
WebElement element = this.driver.findElementByLinkText("linkText");
element.click(); //the code does not execute after this point for the 3rd app
...
}
单击它会产生完全相同的结果。对于上面的代码,我已确保获得了正确的元素。
谁能告诉我我遇到的问题是什么?
在应用程序方面,我不能透露任何有关html代码的信息。我知道这会让解决问题变得更加困难,为此我提前道歉。
===更新2013-04-10 ===
因此,我将源添加到我的爬虫中,并查看了 this.driver.get(url) 中它被卡住的位置。
基本上,驱动程序会迷失在无限刷新循环中。在由 HtmlUnitDriver 实例化的 WebClient 对象中,会加载一个 HtmlPage,该 HtmlPage 会不断刷新,似乎没有结束。
以下是 WaitingRefreshHandler 的代码,包含在 com.gargoylesoftware.htmlunit 中:
public void handleRefresh(final Page page, final URL url, final int requestedWait) throws IOException {
int seconds = requestedWait;
if (seconds > maxwait_ && maxwait_ > 0) {
seconds = maxwait_;
}
try {
Thread.sleep(seconds * 1000);
}
catch (final InterruptedException e) {
/* This can happen when the refresh is happening from a navigation that started
* from a setTimeout or setInterval. The navigation will cause all threads to get
* interrupted, including the current thread in this case. It should be safe to
* ignore it since this is the thread now doing the navigation. Eventually we should
* refactor to force all navigation to happen back on the main thread.
*/
if (LOG.isDebugEnabled()) {
LOG.debug("Waiting thread was interrupted. Ignoring interruption to continue navigation.");
}
}
final WebWindow window = page.getEnclosingWindow();
if (window == null) {
return;
}
final WebClient client = window.getWebClient();
client.getPage(window, new WebRequest(url));
}
指令“client.getPage(window, new WebRequest(url))”再次调用WebClient来重新加载页面,只是再次调用这个完全相同的刷新方法。这似乎会无限期地持续下去,不会很快填满内存,只是因为“Thread.sleep(秒 * 1000)”,它强制在重试之前等待 3m。
有人对我如何解决这个问题有任何建议吗?我收到建议创建 2 个新的 HtmlUnitDriver 和 WebClient 类来扩展原始类。然后重写相关方法以避免这个问题。
再次感谢。
最佳答案
我通过创建一个不执行任何操作的 RefreshHandler 类解决了我永恒的刷新问题:
public class RefreshHandler implements com.gargoylesoftware.htmlunit.RefreshHandler {
public RefreshHandler() { }
public void handleRefresh(final Page page, final URL url, final int secods) { }
}
此外,我还扩展了 HtmlUnitDriver 类,并通过重写修改 WebClient 方法,设置了新的 RefreshHandler:
public class HtmlUnitDriverExt extends HtmlUnitDriver {
public HtmlUnitDriverExt(BrowserVersion version) {
super(version);
}
@Override
protected WebClient modifyWebClient(WebClient client) {
client.setRefreshHandler(new RefreshHandler());
return client;
}
}
modifyWebClient 方法是在 HtmlUnitDriver 中为此目的创建的一个不执行任何操作的方法。
干杯。
关于java - HtmlUnitDriver 在获取 url 时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15838526/