基于HtmlUnit的转换网关的调研
一、前言:
目前大部分移动终端(手机)对javascript支持程度不高,这使得Web网站上很多交互操作无法无缝地迁移到手机上,只有部分高端手机(如IPHONE)除外,目前对javascript的解决策略无外乎三种,即富客户端的B/S结构、中等客户端的C/S结构和一般客户端的S结构。
三种策略相比,第一种对客户端功能要求比较高,相当于将PC浏览器移植到手机上,不仅对客户端硬件要求高,而且移植复杂度比较大;第二种策略,客户端完成一部分javascript的解析,服务端完成一部分解析,二者通过协作,完成脚本的支持,这种策略需要定义一套交互的协议,较少了客户端的开发工作量,同时对服务端的要求也不高,现阶段比较实用;第三种策略,全部javascript的解析工作都集中在服务端进行,客户端收到的响应中不包含javascript,这种策略对服务端处理过程要求比较高,同时需要定义客户端触发脚本的策略,但是这种策略之下,客户端与服务端进行的交互较少,有助于减少流量。
三种策略分别代表了三个阶段,策略三可以作为策略一、二的初级阶段,有了服务端对脚本的支持,才可能有策略二中服务端跟客户端的合作,有了策略一、二的积累,才最终实现脱离服务端的策略一的实现。
本文档主要针对如何在服务端支持javascript对HtmlUnit工具进行了调研,看能否将这个Java版的浏览器集成到服务端用于脚本的解析。
二、主要工作:
1.以HtmlUnit在页面自动化测试以及在搜索引擎方面的应用为切入点,熟悉了该工具的功能。
2.编写了测试代码,获取了HtmlUnit对javascript解析的耗时情况
3.总结了HtmlUnit应用于服务端脚本解析的下一步工作
下面将编写的测试代码贴出来:
try { //创建浏览器,可以选择IE、FF等等 WebClient client = new WebClient( BrowserVersion.INTERNET_EXPLORER_8 ,"192.168.8.175", 28089 ); //获取某网站页面 client.setThrowExceptionOnScriptError( false ); client.setCssEnabled( false ); long start = System.currentTimeMillis(); HtmlPage page = client.getPage("http://www.qingke800.com/index.jsp"); System.out.println( "GetPage Cost Time : " + ( System.currentTimeMillis() - start ) + " ms" ); for( int i = 0; i < 3; i ++ ) { start = System.currentTimeMillis(); page = client.getPage( "http://www.qingke800.com/index.jsp" ); System.out.println( "GetPage" + i + "Cost Time : " + (System.currentTimeMillis() - start ) + "ms" ); start = System.currentTimeMillis(); List<HtmlAnchor> anchors = (List<HtmlAnchor>) page.getByXPath( ".//*[@id='con_three_1']/div[2]/dl[1]/dd[2]/a" ); HtmlAnchor anchor = anchors.get( 0 ); // System.out.println( anchor.getAttribute( "href" ) ); HtmlPage resultPage = anchor.click(); System.out.println( "Click " + i + "Cost Time : " + ( System.currentTimeMillis() - start ) + " ms" ); // System.out.println( "Result Page is : " + resultPage.getWebResponse().getContentAsString() ); } } catch( Exception e ) { e.printStackTrace(); }
这段代码主要测试HtmlUnit在获取页面、执行脚本生成结果页面的效率,HtmlUnit获取页面以及页面中的js代码是通过一个HTTP网关(192.168.8.175:28089),为了排除其他因素的影响,该网关将link标签、iframe标签、img标签进行了过滤,执行结果如下:
GetPageCostTime:54835ms
GetPage0CostTime:22667ms
Click0CostTime:22637ms
GetPage1CostTime:24415ms
Click1CostTime:24119ms
GetPage2CostTime:30265ms
Click2CostTime:22153ms
这里从网关的日志可以看出HtmlUnit具有本地缓存功能,第一次从一个HTML页面中获取了js文件之后,再次刷新时不会重新请求该js,由此可以看出若js文件存储在本地,
联网获取页面时间t1+页面解析生成DOM时间t2+脚本执行时间t3大约等于22s
而与此同时,我也进行了脚本执行时间的估计,具体方法是使用简单的javascript文件(不触发联网),则响应时间如下:
GetPageCostTime:31434ms
GetPage0CostTime:21280ms
Click0CostTime:141ms
GetPage1CostTime:20343ms
Click1CostTime:111ms
GetPage2CostTime:20233ms
Click2CostTime:110ms
由此可以推断,联网获取页面时间t1+页面解析生成DOM时间t2=20s
脚本执行时间t3大约为110ms
这里可以看出,脚本执行并不需要多少时间,关键在于页面获取以及生成DOM。
三、下一步工作:
1.优化DOM生成策略,从源页面规模、DOM生成方面
2.深入研究HtmlUnit的脚本解析和执行策略,看能否可以将脚本执行独立出来