java模拟浏览器包selenium整合了htmlunit,火狐浏览器,IE浏览器,opare浏览器驱

//如果网页源码中有些内容是js渲染过来的,那你通过HttpClient直接取肯定取不到,但是这些数据一般都是通过异步请求传过来的(一般都是通过ajax的get或者post方式)。那么你可以通过火狐浏览器的firebug或者chrome的审查元素,在网络选项中找到这个请求地址,再用HttpClient请求一次就可以拿到你想要的数据,但这些数据可能不是网页源码,一般都是json字符串。
//朋友你好我现在是HtmlUnit运用者,我现在在项目爬去中遇见一个非常棘手的问题,就是分页数据怎样爬取,我现在真的不明白了,朋友可以的话加我QQ452276647 这个问题解决了非常非常的感谢了,
// java模拟浏览器包htmlunit,selenium
//发现一个很不错的模拟浏览器包htmlunit,它可以直接执行访问网站地址,并执行相应的JavaScript脚本;这个功能对于网站爬虫有很大的帮助,一些网站使用了ajax,如果使用简单的http访问只能抓到原始的html源码,但对于页面内执行的ajax却无法获取;使用这个包后,可以将执行ajax后的html源码一并抓取下来。
//网站地址:http://htmlunit.sourceforge.net/
//该站点下边还提到了几个相类似的包:HtmlUnit is used as the underlying "browser" by different Open Source tools like Canoo WebTest, JWebUnit, WebDriver, JSFUnit, Celerity, ...
//canoo WebTest 看了一下,没太明白是怎么用的,没想太深入了解
//jwebunit 是用来做网站测试用的,它整合了JUnit,htmlunit,selenium 包框架;其主要功能是用做白盒测试和压力测试。
//webDriver 后来改名为selenium,它整合了htmlunit,火狐浏览器,IE浏览器,opare浏览器驱动。如果使用htmlunitDriver,则是使用htmlunit包来访问站点;如果使用FirefoxDriver则会直接将Firefox浏览器调出来,然后在浏览器上模拟输入文字和其他鼠标键盘事件。

//htmlunit包访问网站后,获取到html源码后可以对源码进行修改;而jwebunit,selenium则暂时没有发现修改的功能,只是用来做模拟用户操作的功能。

AJAX 网页抓取部分采用调用浏览器 API 的方法,将浏览器虚拟
为一个代理服务器,并将浏览器服务绑定到电脑指定的端口上,通过和这个浏览器
通信并发送网页请求、连接、关闭等指令,实现 AJAX 网页的载入,并将最终载入
完成、重塑之后的网页内容进行保存,并进行后期处理。爬取后的网页将进行去噪、
网页正文抽取和重抓调度等操作。

I am trying to understand testing framework better and been looking into Selenium. I've used HTMLUnit before, mainly when I needed to scrape some information off website or the likes.

In the context of writing test automation, what's the advantage / disadvantages of Selenium vs HTMLUnit? Looks to me Selenium is more complicated to set up than HTMLUnit, although at the same time there's a HTMLUnitDriver for Selenium which I think behave the exact same way as in HTMLUnit itself?

Selenium obviously provides more robust framework, it has the Selenium RC for pararel testing, it also has different browser drivers that can be used - although when you used the browser drivers, the test will actually open/close a browser application rather than headless.

May be I am not understanding Selenium correctly. Some directions and pointers would be great!

On another note - a separate question - I am also looking at doing automated testing on mobile browser, I see that Selenium has an IPhoneDriver for it, but then this is not a headless testing either as it requires actual iOS simulator.

Speaking about parallel testing, it better to use selenium grid. Basic concept of selenium RC and selenium grid.

静态化还有一种思路就要采用HttpClient获取首页生成的html文件保存作为静态页,但是很不幸的,HttpClient无法执行js,所有使用ajax获取的数据都无法获取到,于是这种方式也行不通

最后使用HtmlUnit. HtmlUnit的优势就是可以支持大部分js,对JQuery的支持也不错.大体思路就是先使用HtmlUnit获取执行完js的html, 这个html 生成的样式和html格式会出现一些问题.如果能满足需求则可以直接使用或者略加改动后使用.

很多方案:selenium,phantomjs,casperjs,qtwebkit等。
一般采用的是casperjs。把每个ajax请求完成后保存网页,放入队列,这样的话后面的分析程序就只要分析html就好了。
casperjs这货和nodejs一起使用的时候时不时会有点小问题,如果不想麻烦,npm安装spookyjs,可以把casperjs作为node的模块来使用了。
当然,请求不复杂,无需验证的话,直接观察请求就可以了。

要想做的通用,只能通过浏览器上入手。windows上可以用程序调用IE的浏览器接口来获取页面document,还可以通过chrome或者firefox插件形式来获取要采集的信息后post到服务器上。linux下可以通过phantomjs操纵webit来获取document的内容。phantomjs有好多优点:不依赖X,可以工作在文本模式下,官网里叫做headless;可以抓取页面截图;能监视网络传输;可以禁用图片加载;自定义cookie,自定义头信息等。

使用HtmlUnit. HtmlUnit的优势就是可以支持大部分js,对JQuery的支持也不错.大体思路就是先使用HtmlUnit获取执行完js的html, 这个html 生成的样式和html格式会出现一些问题.如果能满足需求则可以直接使用或者略加改动后使用.

如果这个html不能满足需求,那么就把它当做 为静态数据来使用.这个时候我们先需要一个html模板文件,这个模板文件要保证首页的主题框架,然后从html按照各个div将数据填充进去.下面贴一些实现代码.

//创建一个可执行js,css,ajax的多功能WebClient
        WebClient multiWebClient = new WebClient(BrowserVersion.INTERNET_EXPLORER_8);
        multiWebClient.setJavaScriptEnabled(true);//执行JavaScript
        multiWebClient.setCssEnabled(true);//执行css
        multiWebClient.setAjaxController(new NicelyResynchronizingAjaxController());//设置ajax代理

        //创建一个普通的WebClient
        WebClient commmonWebClient = new WebClient(BrowserVersion.INTERNET_EXPLORER_8);
        commmonWebClient.setJavaScriptEnabled(false);
        commmonWebClient.setCssEnabled(false);

        //用多功能Client获取动态页面的html并执行完js后的页面
        URL dynamicUrl = new URL("http://localhost:30010/WebSite");
        HtmlPage dynamicPage = (HtmlPage) multiWebClient.getPage(dynamicUrl);

        //根据项目需要,使用普通Client加载首页模板(避免执行模板里面的js,这些js都是真正要浏览器查看的时候才会执行)
        URL constantUrl = new URL("http://localhost:30010/WebSite/wwwroot/indexTemple.html");
        HtmlPage htmlpage = (HtmlPage) commmonWebClient.getPage(constantUrl);
        HtmlElement body = htmlpage.getBody(); 

        /**
         * 未详细测试的结论:getElementById一个元素只能取一次,取了之后再取就是空元素,其子也无法用getElementById取到
         * 开始处理header
         */
        appendChildren(body.getElementById("_static_nav"), dynamicPage.getElementById("_static_nav"));

        //开始处理_static_leftbox
        //处理图片滚动KSS_content
        appendChildren(body.getElementById("KinSlideshow"), dynamicPage.getElementById("KSS_content"));
        //处理最新电子书
        appendChildren(body.getElementById("e_bookDiv"), dynamicPage.getElementById("e_bookDiv"));

        //取出content
        HtmlElement content = body.getElementById("content");

        //开始处理_static_rightbox
        content.appendChild(dynamicPage.getElementById("_static_rightbox"));
        //添加div换行
        DomElement clearDiv = htmlpage.createElement("div");
        clearDiv.setAttribute("class", "clear");
        //一个DomElement貌似只能使用一次
        content.appendChild(clearDiv.cloneNode(true));

        //开始处理_static_bookshow
        content.appendChild(dynamicPage.getElementById("_static_bookshow"));
        content.appendChild(clearDiv.cloneNode(true));

        //开始处理_static_assistBox,secrecyRelevancediv,_static_optionBox
        content.appendChild(dynamicPage.getElementById("_static_assistBox"));
        content.appendChild(dynamicPage.getElementById("secrecyRelevancediv"));
        content.appendChild(dynamicPage.getElementById("_static_optionBox"));
        content.appendChild(clearDiv.cloneNode(true));

        //开始处理_static_bookShowA
        content.appendChild(dynamicPage.getElementById("_static_bookShowA"));
        content.appendChild(clearDiv.cloneNode(true));
        //开始处理_static_serve
        content.appendChild(dynamicPage.getElementById("_static_serve"));

        //开始处理footer
        body.appendChild(clearDiv.cloneNode(true));
        body.appendChild(dynamicPage.getElementById("_static_footer"));

        //处理错误
        String finalHtml =htmlpage.asXml().replace("<?xml version=\"1.0\" encoding=\"utf-8\"?>", "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
        finalHtml = finalHtml.replaceAll("<a class=\"prev browse left\"/>", "<a class=\"prev browse left\" ></a>");
        finalHtml = finalHtml.replaceAll("<a class=\"next browse right\"/>", "<a class=\"next browse right\" ></a>");
        finalHtml = finalHtml.replaceAll("<b/>", "<b></b>");
        finalHtml = finalHtml.replaceAll("scrollable_2", "scrollable");
        stringToFile(finalHtml,"E:\\WayOfGlory\\WebSite\\WebContent\\wwwroot\\indexHome.html");

上面一段代码虽然不长,但实际上是个非常漫长的处理过程,从静态数据html中获取到的<div></div>经常会无法直接 使用,这时就需要不断的和浏览器(比如chrome)生成的真正静态页进行比对.虽然过程很漫长,但总比无法实现要强.

下面贴上刚刚使用了的两个小方法.

public DomElement appendChildren(DomElement target,DomElement source){

      Iterator it = source.getChildElements().iterator();
      while(it.hasNext()){
        DomElement ele = (DomElement) it.next();
        target.appendChild(ele);
      }
    		return target;
    	}

    	public void stringToFile(String content,String path){
    		try {
        FileWriterWithEncoding fileWriter = new FileWriterWithEncoding(path,"utf-8");
        fileWriter.write(content);
        fileWriter.flush();
        fileWriter.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    	}

Selenium HtmlUnitDriver多浏览器的支持

  1、HtmlUnitDriver
  WebDriver包括一个基于HtmlUnit的*面实 现,称为HtmlUnitDriver,即使用HtmlUnit时并不会打开真实的浏览器,而是在内存中执行代码,因此运行速度很快,但是对 JavaScript的支持不够好,当页面上有复杂的JavaScript元素时,经常捕捉不到。
  eclipse测试例子如下:
  WebDriver dr = new HtmlUnitDriver();
  dr.get(“http://www.baidu.com“);
  WebElement element = dr.findElement(By.name(“wd”));
  element.sendKeys(“webdriver”);
  element.submit();
  Thread.sleep(5000);
  System.out.println(“page title is:”+dr.getTitle());
  运行成功时控制台会打印百度搜索页面标题“page title is:webdriver_百度搜索”。
  2、Firefox
  WebDriver实现了FireFoxDriver,无需用户下载FireFoxDriver。
  优点:FireFoxDriver对页面的自动化测试支持得比较好,很直观地模拟页面的操作,对JavaScript的支持也非常完善,基本上页面上做的所有操作FireFox Driver都可以模拟。
  缺点:启动很慢,运行也比较慢,不过,启动之后Webdriver的操作速度虽然不快但还是可以接受的,建议不要频繁启动停止FireFoxDriver。
  使用Firefox浏览器只需要设置WebDriver driver = new FirefoxDriver(),前提是你的Firefox被安装在默认的位置。
  操作系统 Firefox默认安装位置
  Linux firefox (found using “which”)
  Mac /Applications/Firefox.app/Contents/MacOS/firefox
  Windows %PROGRAMFILES%\Mozilla Firefox\firefox.exe
  如果你的FireFox没有被安装在指定的位置,可以设置“webdriver.firefox.bin”来指定它的位置,java代码如下:
  System.setProperty(“webdriver.firefox.bin”,”thelocation of Firefox”);
  eclipse测试例子如下:
  System.setProperty(“webdriver.firefox.bin”,”D:\Mozilla Firefox\firefox.exe”);
  WebDriver dr = new FirefoxDriver();
  dr.get(“http://www.baidu.com“);
  WebElement element = dr.findElement(By.name(“wd”));
  element.sendKeys(“webdriver”);
  element.submit();
  Thread.sleep(5000);
  System.out.println(“page title is:”+dr.getTitle());
  3、Chrome
   webdriver没有实现chromedriver,要使用chrome浏览器需要自己下载chromedriver.exe(下载地 址:http://code.google.com/p/chromedriver/downloads/list),这个程序是由Chrome团队提供 的,你可以看做它是链接WebDriver和Chrome浏览器的桥梁。
  eclipse例子如下:
  System.setProperty(“webdriver.chrome.driver”,”D:\chromedriver\chromedriver.exe”); //指定chromedriver的路径
   System.setProperty(“webdriver.chrome.bin”,”C:\Documents and Settings\gongjf\Local Settings\Application Data\Google\Chrome\Application\chrome.exe”); //chrome没有安装在默认路径时,指定chrome.exe的路径
  WebDriver driver = new ChromeDriver();
  driver.get(“http://www.baidu.com“);
  4、IE
   webdriver要使用IE浏览器需要下载InternetExplorerDriver.exe(下载地 址:http://code.google.com/p/selenium/downloads/list),根据浏览器的版本下载32位或者64位的 driver。
  注意:需要将IE浏览器各个区域的保护模式设置的一样,要么全勾选,要么全不勾选,工具–Internet选项–安全。还需要将页面的缩放比例设置为100%
  优点:直观地模拟用户的实际操作,对JavaScript提供完善的支持。
  缺点:是所有浏览器中运行速度最慢的,并且只能在Windows下运行,对CSS以及XPATH的支持也不够好。
   System.setProperty(“webdriver.ie.driver”,”D:\iedriver\IEDriverServer.exe”); //设置IEDriverService.exe的路径;如果IE没有安装在默认目录,同样需要设置webdriver.ie.bin
  WebDriver driver = new InternetExplorerDriver();
  driver.get(“http://www.baidu.com“);
上一篇:bzoj2884 albus就是要第一个出场


下一篇:ubuntu 修改主机名