https://github.com/apache/incubator-zeppelin/blob/master/zeppelin-server/src/test/java/com/webautomation/ScreenCaptureHtmlUnitDriver.java

http://stackoverflow.com/questions/36254656/not-able-to-take-screenshot-using-htmlunitdriver-selenium-webdriver-java

/*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements. See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
   
  package com.webautomation;
   
  import java.io.ByteArrayOutputStream;
  import java.io.File;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.net.URL;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.Map;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  import java.util.zip.ZipEntry;
  import java.util.zip.ZipOutputStream;
   
  import org.apache.commons.io.FilenameUtils;
  import org.apache.commons.io.IOUtils;
  import org.openqa.selenium.Capabilities;
  import org.openqa.selenium.OutputType;
  import org.openqa.selenium.TakesScreenshot;
  import org.openqa.selenium.WebDriverException;
  import org.openqa.selenium.htmlunit.HtmlUnitDriver;
  import org.openqa.selenium.internal.Base64Encoder;
  import org.openqa.selenium.remote.CapabilityType;
  import org.openqa.selenium.remote.DesiredCapabilities;
   
  import com.gargoylesoftware.htmlunit.BrowserVersion;
  import com.gargoylesoftware.htmlunit.WebClient;
  import com.gargoylesoftware.htmlunit.WebRequest;
  import com.gargoylesoftware.htmlunit.WebWindow;
  import com.gargoylesoftware.htmlunit.html.HtmlElement;
  import com.gargoylesoftware.htmlunit.html.HtmlPage;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
   
  /**
  * from https://code.google.com/p/selenium/issues/detail?id=1361
  */
  public class ScreenCaptureHtmlUnitDriver extends HtmlUnitDriver implements TakesScreenshot {
   
  private static Map<String, byte[]> imagesCache = Collections.synchronizedMap(new HashMap<String, byte[]>());
   
  private static Map<String, String> cssjsCache = Collections.synchronizedMap(new HashMap<String, String>());
   
  // http://stackoverflow.com/questions/4652777/java-regex-to-get-the-urls-from-css
  private final static Pattern cssUrlPattern = Pattern.compile("background(-image)?[\\s]*:[^url]*url[\\s]*\\([\\s]*([^\\)]*)[\\s]*\\)[\\s]*");// ?<url>
   
  static Logger LOGGER = LoggerFactory.getLogger(ScreenCaptureHtmlUnitDriver.class);
   
  public ScreenCaptureHtmlUnitDriver() {
  super();
  }
   
  public ScreenCaptureHtmlUnitDriver(boolean enableJavascript) {
  super(enableJavascript);
  }
   
  public ScreenCaptureHtmlUnitDriver(Capabilities capabilities) {
  super(capabilities);
  }
   
  public ScreenCaptureHtmlUnitDriver(BrowserVersion version) {
  super(version);
  DesiredCapabilities var = ((DesiredCapabilities) getCapabilities());
  var.setCapability(CapabilityType.TAKES_SCREENSHOT, true);
  }
   
  @Override
  @SuppressWarnings("unchecked")
  public <X> X getScreenshotAs(OutputType<X> target) throws WebDriverException {
  byte[] archive = new byte[0];
  try {
  archive = downloadCssAndImages(getWebClient(), (HtmlPage) getCurrentWindow().getEnclosedPage());
  } catch (Exception e) {
  LOGGER.error("Exception in ScreenCaptureHtmlUnitDriver while getScreenshotAs ", e);
  }
  if(target.equals(OutputType.BASE64)){
  return target.convertFromBase64Png(new Base64Encoder().encode(archive));
  }
  if(target.equals(OutputType.FILE)){
  File f = new File("screen.tmp");
  try {
  FileOutputStream scr = new FileOutputStream(f);
  scr.write(archive);
  scr.close();
  } catch (IOException e) {
  throw new WebDriverException(e);
  }
  return (X) f;
  }
  return (X) archive;
  }
   
  // http://stackoverflow.com/questions/2244272/how-can-i-tell-htmlunits-webclient-to-download-images-and-css
  protected byte[] downloadCssAndImages(WebClient webClient, HtmlPage page) throws Exception {
  WebWindow currentWindow = webClient.getCurrentWindow();
  Map<String, String> urlMapping = new HashMap<String, String>();
  Map<String, byte[]> files = new HashMap<String, byte[]>();
  WebWindow window = null;
  try {
  window = webClient.getWebWindowByName(page.getUrl().toString()+"_screenshot");
  webClient.getPage(window, new WebRequest(page.getUrl()));
  } catch (Exception e) {
  LOGGER.error("Exception in ScreenCaptureHtmlUnitDriver while downloadCssAndImages ", e);
  window = webClient.openWindow(page.getUrl(), page.getUrl().toString()+"_screenshot");
  }
   
  String xPathExpression = "//*[name() = 'img' or name() = 'link' and (@type = 'text/css' or @type = 'image/x-icon') or @type = 'text/javascript']";
  List<?> resultList = page.getByXPath(xPathExpression);
   
  Iterator<?> i = resultList.iterator();
  while (i.hasNext()) {
  try {
  HtmlElement el = (HtmlElement) i.next();
  String resourceSourcePath = el.getAttribute("src").equals("") ? el.getAttribute("href") : el
  .getAttribute("src");
  if (resourceSourcePath == null || resourceSourcePath.equals(""))
  continue;
  URL resourceRemoteLink = page.getFullyQualifiedUrl(resourceSourcePath);
  String resourceLocalPath = mapLocalUrl(page, resourceRemoteLink, resourceSourcePath, urlMapping);
  urlMapping.put(resourceSourcePath, resourceLocalPath);
  if (!resourceRemoteLink.toString().endsWith(".css")) {
  byte[] image = downloadImage(webClient, window, resourceRemoteLink);
  files.put(resourceLocalPath, image);
  } else {
  String css = downloadCss(webClient, window, resourceRemoteLink);
  for (String cssImagePath : getLinksFromCss(css)) {
  URL cssImagelink = page.getFullyQualifiedUrl(cssImagePath.replace("\"", "").replace("\'", "")
  .replace(" ", ""));
  String cssImageLocalPath = mapLocalUrl(page, cssImagelink, cssImagePath, urlMapping);
  files.put(cssImageLocalPath, downloadImage(webClient, window, cssImagelink));
  }
  files.put(resourceLocalPath, replaceRemoteUrlsWithLocal(css, urlMapping)
  .replace("resources/", "./").getBytes());
  }
  } catch (Exception e) {
  LOGGER.error("Exception in ScreenCaptureHtmlUnitDriver while resultList.iterator ", e);
  }
  }
  String pagesrc = replaceRemoteUrlsWithLocal(page.getWebResponse().getContentAsString(), urlMapping);
  files.put("page.html", pagesrc.getBytes());
  webClient.setCurrentWindow(currentWindow);
  return createZip(files);
  }
   
  String downloadCss(WebClient webClient, WebWindow window, URL resourceUrl) throws Exception {
  if (cssjsCache.get(resourceUrl.toString()) == null) {
  cssjsCache.put(resourceUrl.toString(), webClient.getPage(window, new WebRequest(resourceUrl))
  .getWebResponse().getContentAsString());
   
  }
  return cssjsCache.get(resourceUrl.toString());
  }
   
  byte[] downloadImage(WebClient webClient, WebWindow window, URL resourceUrl) throws Exception {
  if (imagesCache.get(resourceUrl.toString()) == null) {
  imagesCache.put(
  resourceUrl.toString(),
  IOUtils.toByteArray(webClient.getPage(window, new WebRequest(resourceUrl)).getWebResponse()
  .getContentAsStream()));
  }
  return imagesCache.get(resourceUrl.toString());
  }
   
  public static byte[] createZip(Map<String, byte[]> files) throws IOException {
  ByteArrayOutputStream bos = new ByteArrayOutputStream();
  ZipOutputStream zipfile = new ZipOutputStream(bos);
  Iterator<String> i = files.keySet().iterator();
  String fileName = null;
  ZipEntry zipentry = null;
  while (i.hasNext()) {
  fileName = i.next();
  zipentry = new ZipEntry(fileName);
  zipfile.putNextEntry(zipentry);
  zipfile.write(files.get(fileName));
  }
  zipfile.close();
  return bos.toByteArray();
  }
   
  List<String> getLinksFromCss(String css) {
  List<String> result = new LinkedList<String>();
  Matcher m = cssUrlPattern.matcher(css);
  while (m.find()) { // find next match
  result.add( m.group(2));
  }
  return result;
  }
   
  String replaceRemoteUrlsWithLocal(String source, Map<String, String> replacement) {
  for (String object : replacement.keySet()) {
  // background:url(http://org.com/images/image.gif)
  source = source.replace(object, replacement.get(object));
  }
  return source;
  }
   
  String mapLocalUrl(HtmlPage page, URL link, String path, Map<String, String> replacementToAdd) throws Exception {
  String resultingFileName = "resources/" + FilenameUtils.getName(link.getFile());
  replacementToAdd.put(path, resultingFileName);
  return resultingFileName;
  }
   
  }

ScreenCaptureHtmlUnitDriver.java的更多相关文章

  1. Spark案例分析

    一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...

  2. 故障重现(内存篇2),JAVA内存不足导致频繁回收和swap引起的性能问题

    背景起因: 记起以前的另一次也是关于内存的调优分享下   有个系统平时运行非常稳定运行(没经历过大并发考验),然而在一次活动后,人数并发一上来后,系统开始卡. 我按经验开始调优,在每个关键步骤的加入如 ...

  3. Elasticsearch之java的基本操作一

    摘要   接触ElasticSearch已经有一段了.在这期间,遇到很多问题,但在最后自己的不断探索下解决了这些问题.看到网上或多或少的都有一些介绍ElasticSearch相关知识的文档,但个人觉得 ...

  4. 论:开发者信仰之“天下IT是一家“(Java .NET篇)

    比尔盖茨公认的IT界领军人物,打造了辉煌一时的PC时代. 2008年,史蒂夫鲍尔默接替了盖茨的工作,成为微软公司的总裁. 2013年他与微软做了最后的道别. 2013年以后,我才真正看到了微软的变化. ...

  5. 故障重现, JAVA进程内存不够时突然挂掉模拟

    背景,服务器上的一个JAVA服务进程突然挂掉,查看产生了崩溃日志,如下: # Set larger code cache with -XX:ReservedCodeCacheSize= # This ...

  6. 死磕内存篇 --- JAVA进程和linux内存间的大小关系

    运行个JAVA 用sleep去hold住 package org.hjb.test; public class TestOnly { public static void main(String[] ...

  7. 【小程序分享篇 一 】开发了个JAVA小程序, 用于清除内存卡或者U盘里的垃圾文件非常有用

    有一种场景, 手机内存卡空间被用光了,但又不知道哪个文件占用了太大,一个个文件夹去找又太麻烦,所以我开发了个小程序把手机所有文件(包括路径下所有层次子文件夹下的文件)进行一个排序,这样你就可以找出哪个 ...

  8. Java多线程基础学习(二)

    9. 线程安全/共享变量——同步 当多个线程用到同一个变量时,在修改值时存在同时修改的可能性,而此时该变量只能被赋值一次.这就会导致出现“线程安全”问题,这个被多个线程共用的变量称之为“共享变量”. ...

  9. Java多线程基础学习(一)

    1. 创建线程    1.1 通过构造函数:public Thread(Runnable target, String name){}  或:public Thread(Runnable target ...

随机推荐

  1. Infix to postfix conversion 中缀表达式转换为后缀表达式

    Conversion Algorithm 1.操作符栈压入"#": 2.依次读入表达式的每个单词: 3.如果是操作数则压入操作数栈: 4.如果是操作符,则将操作符栈顶元素与要读入的 ...

  2. redis第一篇--综述

    1 redis里边有数据库的概念.可分为1-255这些表.在存储或者查找的时候要指明. redis_sentinel 集群里边封装成了namespace这样的概念.与db是不一样的.

  3. mongodb备份

    一:数据导出,数据导入作为DBA(管理员),经常会碰到导入导出数据的需求,下面介绍实用工具(自带的):1:数据导入 mongoexport导出csv格式的文件./mongoexport -d Test ...

  4. sql 比较2个test字段的值

    可以用 CAST([TEXT字段]AS VARCHAR(MAX)),然后再比较

  5. 【威佐夫博奕】 betty定理 poj 1067

    Description 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相同数量的石子.最后 ...

  6. linux命令-sed,uniq,cut,wc

    sort sort 命令对 File 参数指定的文件中的行排序,并将结果写到标准输出.如果 File 参数指定多个文件,那么 sort 命令将这些文件连接起来,并当作一个文件进行排序. sort语法 ...

  7. Vim编辑器的使用和基本配置

    三种模式 1 命令模式 插入 a i o A I O 定位 gg G :n nG ngg $ 0 删除 x nx dd ndd dG 复制和剪切 yy-p dd-p 替换 r R 撤销和恢复 u Ct ...

  8. material design 的android开源代码整理

    material design 的android开源代码整理 1 android (material design 效果的代码库) 地址请点击:MaterialDesignLibrary 效果: 2 ...

  9. C# Excel嵌入到Winform

    本文讲的这个技术是把Excel表格嵌入到自己开发程序的Form窗体中进行操作,给客户一个不用切换窗口的操作界面,似乎更好.这在VC中用OLE技术很容易实现,但是在C#中方法就不一样啦.下面将就此进行阐 ...

  10. 尝试在数据库 5 中提取逻辑页 (1:1640) 失败。该逻辑页属于分配单元XXX ,而非 XXX。

    此信息表明数据库或表 已经部分损坏可以通过以下步骤尝试修复: 1. DBCC CHECKDB 重启服务器后,在没有进行任何操作的情况下,在SQL查询分析器中执行以下SQL进行数据库的修复,修复数据库存 ...