htmlUnit的读取js渲染的页面
我这边有个这么的需求,要求前端每次上版本的时候,有一个版本号。然后后端去爬前端,比较禅道的版本发布计划,如果发布计划和生产上的版本号不一致,就告警。
这个跟后端的jar包,每次打包,读取该分支的git号,然后打包到jar包一样,这样每次发版就知道当前的版本是什么版本了。
前端那边摸索出来了,但是读取的时候出了点问题。前端提供的页面,如果用浏览器去浏览,是很正常的。然后用httpclient去读取,发现没有对应的标签。
很明显,这个是因为,这个结构是js渲染后生成的,这样的话,就得换工具了。
百度了下,发现java用的是htmlunit。
工具类是这样。
public class MyHtmlUnitHelper {
public static Document accordingToURLGetBrowserHtml(String requestUrl) throws InterruptedException, MalformedURLException {
final WebClient webClient = new WebClient(BrowserVersion.FIREFOX_ESR);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
webClient.getOptions().setActiveXNative(false);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setDownloadImages(false);
webClient.getOptions().setActiveXNative(false);
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
webClient.getOptions().setUseInsecureSSL(true);
webClient.setWebConnection(
new WebConnectionWrapper(webClient) {
@Override
public WebResponse getResponse(WebRequest request) throws IOException {
WebResponse response = super.getResponse(request);
return response;
}
}
);
HtmlPage page = null;
try {
page = webClient.getPage(requestUrl);
} catch (Exception e) {
e.printStackTrace();
}finally {
webClient.close();
}
webClient.waitForBackgroundJavaScript(30000);
String pageXml = page.asXml();
Document parse = Jsoup.parse(pageXml);
return parse;
}
public static void main(String[] args) throws InterruptedException, MalformedURLException {
Document document = MyHtmlUnitHelper.accordingToURLGetBrowserHtml("https://xjczgl.zjxj.gov.cn/#/version");
Elements big = document.getElementsByTag("big");
String text = big.text();
System.out.println(text);
}
}
<!--jsoup 是一款 Java 的HTML 解析器-->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.13.1</version>
</dependency>
<!--模拟一个无头浏览器-->
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>2.60.0</version>
</dependency>
这个工具能模拟浏览器,执行js。然后将读取到的内容用html解析器jsoup去读取。这样我就能读取到对应的版本号了。
但是又出现了一个问题,我发现本地的前端能爬到,而生产的却爬不到,然后我看了下,本地执行js是没问题的,而生产的js执行却有问题。
为啥?本地和生产的区别,无非就是nginx。是不是nginx的gzip的原因?
因为开启了gzip,然后导致js执行有问题,然后我改了下测试的nginx,关闭了gzip,再去爬,记过还是js执行失败。这我就抓瞎了,为什么我本地能执行成功,生产却执行失败。是字符集还是换行符的问题?
我看了下报错
很明显,是js执行错误。那就debug吧。
emm,很清楚了,就是执行这个js的时候,这个js里面有特殊字符。估计就是换行符了。
那怎么办呢?
要么改js,要么就读取的时候,替换换行符了。
但是我感觉不太对,为什么我非得读动态生成的版本号。
我直接让前端给我提供一个json文件,我读取静态的json文件就好。
一了百了。
|