进行各种各样的网页爬虫过程中,有些网页直接httpclient拿过来就能用,但是有些网站是需要等待js加载样式或者某些值的,使用httpclient没办法设置js等待时间,然后再抓取值。
htmlunit可以完美解决这个问题。但是在使用htmlunit访问网页时 经常会出现各种网页的JavaScript加载过程中的警告与提示信息 例如:
ERROR c.g.h.javascript.DefaultJavaScriptErrorListener - Error during JavaScript execution com.gargoylesoftware.htmlunit.ScriptException: URIError: Malformed URI sequence.
在代码中已经对WebClient进行设置了webClient.getOptions().setThrowExceptionOnScriptError(false);
并不能关闭这些提示信息 导致每次访问网页都会打印一大串一大串的无用信息
我并不关心他js报什么错,我只关心拿下来页面的结果。通过查看这个报错类,重写它里面的方法,把所有log输出语句全部删除,就可以达到不打印错误信息的作用了。
类路径是:com.gargoylesoftware.htmlunit.javascript.DefaultJavaScriptErrorListener
解决方法代码如下
private String getTimeByHtmlUnit(String url) throws IOException {
if (StringUtils.isBlank(url)) {
return "";
}
WebClient webClient = new WebClient(BrowserVersion.CHROME);
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setActiveXNative(false);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
webClient.getOptions().setTimeout(5000);
// -----重点-----设置为我们自定义的错误处理类
webClient.setJavaScriptErrorListener(new MyJSErrorListener());
webClient.setJavaScriptTimeout(5000);
HtmlPage page = webClient.getPage(url);
//wait for js execute
webClient.waitForBackgroundJavaScript(3000);
//这里是我的爬取目标 忽略即可
DomNodeList<DomElement> domElements = page.getElementsByTagName("relative-time");
if (domElements.isEmpty()) {
return "";
}
return domElements.get(0).getAttribute("datetime");
}
/**
忽略html unit打印的所有js加载报错信息
*/
public class MyJSErrorListener extends DefaultJavaScriptErrorListener {
@Override
public void scriptException(HtmlPage page, ScriptException scriptException) {
}@Override
public void timeoutError(HtmlPage page, long allowedTime, long executionTime) {
}@Override
public void malformedScriptURL(HtmlPage page, String url, MalformedURLException malformedURLException) {}
@Override
public void loadScriptError(HtmlPage page, URL scriptUrl, Exception exception) {}
@Override
public void warn(String message, String sourceName, int line, String lineSource, int lineOffset) {}
}