网页爬虫修改js文件
程序员文章站
2022-03-08 15:44:13
...
window.href = url+window.screen.height;
java程序或者python程序无法通过修改window.screen.height来模拟参数,那么这就需要修改js文件window.href = url+1024;
我们要在浏览器对js进行debug并且修改,修改完并通过console.log类似的功能输出指定的数据,那么java程序如何修改js代码?或者获取这些指定的数据?可以使用giant-htmlunit。
package test; import java.io.IOException; import java.net.MalformedURLException; import java.util.Map; import org.apache.commons.collections.map.HashedMap; import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; import com.gargoylesoftware.htmlunit.fetch.FetchWebContext; import com.gargoylesoftware.htmlunit.html.HtmlPage; import com.gargoylesoftware.htmlunit.vo.fetch.ReloadContextVo; /** * 自制giant-htmlunit可以处理webclient多线程抓取网页,以便htmlunit更好的支持代理ip,拨号ip。节省更多的硬件资源。 * 本用例用于测试 giant-htmlunit,处理js文件进行测试,(支持gzip流格式文件的修改) * context.asynCloseWebAllWindows();支持主线程异步关闭浏览器开启的job线程,htmlunit默认的close,是会等待job执行完毕的,不能预期关闭webclient,这样会大量占用内存跟线程资源,容易oom,asynCloseWebAllWindows很好的解决了该问题。 * @author lyq */ public class TestGiantClient { public static void main(String[] args) throws FailingHttpStatusCodeException, MalformedURLException, IOException { // updateJs(); // setWait(); // replaceJsResoure();//如果修改原始js太麻烦了,可以把js下载回来修改,修改完替换整个js skipUrl(); } /** * @throws IOException * cacheTest1.html 引入js1.js文件,修改js1.js代码,并执行。 * */ public static void updateJs() throws IOException{ FetchWebContext context = new FetchWebContext(); ReloadContextVo contextVo = new ReloadContextVo(); Map<String, ReloadContextVo> map = new HashedMap(); map.put("/js/js", contextVo);//识别url,如果url改变了,这个标识不变的情况下会重新加载js,比如说js/js1.js改成js2.js,最后会重新加载js2.js;现在流行单页面程序,像vue发布时候会重新生成js,加上后缀,这里正确设置,会重新加载最新的js context.getFetchWebClient().cacheFile("/js/js"); contextVo.setStatic(true);//如果只替换一次,那么设置成true;如果需要动态替换,设置成false // contextVo.add(arg0, arg1); contextVo.add("(func1\\(\\)[\\w\\W]+?return\\s+?\")[\\w\\W]+?(\")","$1方法func1被修改了。。。$2");//类似 string。replaceAll方法,替换js代码 context.getFetchWebClient().setRegexToValue(map); try{ HtmlPage page = (HtmlPage)context.getFetchWebClient().getPage("http://127.0.0.1:8085/test1/cacheTest1.html"); // context.getFetchWebClient().set Object result = context.getFetchWebClient().getJavaScriptEngine().execute(page,"func1()" , "injected script", 1); System.out.println(result);//这里输出“方法func1被修改了” }catch(Exception e){ context.asynCloseWebAllWindows(); } } /** * * @throws IOException * testWait.html 引入js文件waitJs.js文件,主程序等待waitJs。js里面的代码执行完毕再继续跑。 * addFilter× 与 waitFilter× 配对方法; 等待浏览器执行完js指定输出后再继续跑主程序 */ public static void setWait() throws IOException{ FetchWebContext context = new FetchWebContext(); try{ context.getFetchWebClient().addFilterConsoleForStop("wait log1"); HtmlPage html = (HtmlPage)context.getFetchWebClient().getPage("http://127.0.0.1:8085/test1/testWait.html"); // context.getFetchWebClient().set Long start = System.currentTimeMillis(); //这里找不到waitJs.js输出日志 "wait log1",所以会等待十秒钟,执行失败 context.getFetchWebClient().waitFilterConsoleForStop("wait log1", 10000); // String result = context.getFetchWebClient().getConsoleResult(); System.out.println(context.getFetchWebClient().getFilterUrlMap().size()+"花费时间:"+(System.currentTimeMillis()-start)); context.getFetchWebClient().addFilterConsoleForStop("wait log"); html = (HtmlPage)context.getFetchWebClient().getPage("http://127.0.0.1:8085/test1/testWait.html"); // context.getFetchWebClient().set start = System.currentTimeMillis(); //这里找不到waitJs.js输出日志 "wait log1",所以会等待js输出 wait log,执行成功 context.getFetchWebClient().waitFilterConsoleForStop("wait log", 10000); // String result = context.getFetchWebClient().getConsoleResult(); System.out.println(context.getFetchWebClient().getFilterUrlMap().size()+"花费时间:"+(System.currentTimeMillis()-start)); }catch(Exception e){ context.asynCloseWebAllWindows(); } } /** * @throws IOException *testWait.html 引入js文件js1.js文件;主程序获取js2.js代替js1.js内容; * */ public static void replaceJsResoure() throws IOException{ FetchWebContext context = new FetchWebContext(); ReloadContextVo vo = new ReloadContextVo(); context.getFetchWebClient().cacheFile("js/js"); try{ context.url2url("http://127.0.0.1:8085/js/js1.js", "http://127.0.0.1:8085/js/js2.js"); context.getFetchWebClient().addFilterConsoleForResult("my result:"); HtmlPage html = (HtmlPage)context.getFetchWebClient().getPage("http://127.0.0.1:8085/test1/cacheTest1.html"); // context.getFetchWebClient().set context.getFetchWebClient().waitFilterConsoleResult("my result:", 1000); String result = context.getFetchWebClient().getConsoleResult(); System.out.println(result);//输出我是js2 }catch(Exception e){ context.asynCloseWebAllWindows(); } } /** * @throws IOException * 跳过指定路径不获取 * */ public static void skipUrl() throws IOException{ FetchWebContext context = new FetchWebContext(); ReloadContextVo vo = new ReloadContextVo(); try{ context.getSkipUrls().add("/js/js"); HtmlPage html = (HtmlPage)context.getFetchWebClient().getPage("http://127.0.0.1:8085/test1/cacheTest1.html"); /*** * 这里跳过了含/js/js了路径,也就是不会再获取js文件 */ System.out.println(html); }catch(Exception e){ e.printStackTrace(); context.asynCloseWebAllWindows(); } } }
<dependency> <groupId>com.giant</groupId> <artifactId>giant-htmlunit</artifactId> <version>2.26.8</version> <scope>compile</scope> </dependency> <!--如果raw.githubusercontent.com不能下载参照https://blog.csdn.net/Mirt_/article/details/106011435--> <repository> <id>framework</id> <name>framework</name> <url>https://raw.githubusercontent.com/jzft/framework/master/repository/</url> <snapshots> <enabled>false</enabled> </snapshots> </repository>
//cacheTest1.html代码 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>cacheTest1.html</title> </head> <body> <script src="/js/js1.js"></script> </body> </html>
//cacheTest2.html代码 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>cacheTest2.html</title> </head> <body> <script src="/js/js2.js"></script> </body> </html>
//testWait.html代码 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>TestWait</title> </head> <body> <script src="/js/waitJs.js"></script> </body> </html> </html>
//js1.js代码 console.log("my result:我是js1") function func1(){ return "func1 execute" }
//js2.js代码 console.log("my result:我是js2")
//waitJs.js代码 setTimeout(function(){ console.log("wait log !"); },3000)