日期:2014-05-17  浏览次数:20622 次

基于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标签进行了过滤,执行结果如下:
    GetPage Cost Time : 54835 ms
    GetPage0Cost Time : 22667ms
    Click 0Cost Time : 22637 ms
    GetPage1Cost Time : 24415ms
    Click 1Cost Time : 24119 ms
    GetPage2Cost Time : 30265ms
    Click 2Cost Time : 22153 ms
    这里从网关的日志可以看出HtmlUnit具有本地缓存功能,第一次从一个HTML页面中获取了js文件之后,再次刷新时不会重新请求该js,由此可以看出若js文件存储在本地,
     联网获取页面时间 t1 + 页面解析生成DOM时间t2 + 脚本执行时间 t3 大约等于 22s
    而与此同时,我也进行了脚本执行时间的估计,具体方法是使用简单的javascript文件(不触发联网),则响应时间如下:
     GetPage Cost Time : 31434 ms
    GetPage0Cost Time : 21280ms
    Click 0Cost Time : 141 ms
    GetPage1Cost Time : 20343ms
    Click 1Cost Time : 111 ms
    GetPage2Cost Time : 20233ms
    Click 2Cost Time : 110 ms
     由此可以推断,联网获取页面时间 t1 + 页面解析生成DOM时间 t2 = 20s
                 脚本执行时间 t3 大约为 110ms
     这里可以看出,脚本执行并不需要多少时间,关键在于页面获取以及生成DOM。

三、下一步工作:
    
     1. 优化DOM生成策略,从源页面规模、DOM生成方面
   &n