【问题标题】:PhantomJS to screenshot website div for Spring MVC, Tomcat and iText usePhantomJS 为 Spring MVC、Tomcat 和 iText 使用截屏网站 div
【发布时间】:2014-03-23 20:50:22
【问题描述】:

我已经了解了 PhantomJS 和 CasperJS 的强大功能来获取网站截图。文章“Responsive Screenshots With Casper”对了解这两种技术的基础知识以及屏幕截图功能非常有帮助。

接下来是如何将此技术用于与 Spring MVC 应用程序的集成。

到目前为止,我已经尝试过“Screen Capture using PhantomJS, GhostDriver, Selenium Hub”的代码,并将其与“Remote PhantomJS driver in Junit”中提供的answer结合起来。

发生的情况是,每次我运行程序时,我都会收到一个ClassNotFoundError,并且我一直提供丢失的 JAR 文件。我最终在我的 Spring 应用程序中下载并提供了九个新的 JAR 文件:

  • phantomjsdriver-1.0.4.jar
  • selenium-java-2.39.0.jar 及其源文件
  • asm-all-3.3.1.jar
  • cglib-3.1.jar
  • commons-exec-1.2.jar
  • guava-16.0.1.jar
  • httpclient-4.3.2.jar
  • httpcore-4.3.2.jar
  • json-20140107.jar

直到出现下面的错误

SEVERE: Servlet.service() for servlet [spring] in context with path [/my_spring_app] threw exception [Handler processing failed; nested exception is java.lang.IncompatibleClassChangeError: class net.sf.cglib.core.DebuggingClassWriter has interface org.objectweb.asm.ClassVisitor as super class] with root cause
java.lang.IncompatibleClassChangeError: class net.sf.cglib.core.DebuggingClassWriter has interface org.objectweb.asm.ClassVisitor as super class

我是否应该继续尝试这条路径以获取我网站的屏幕截图?我觉得这是一场失败的战斗,基于正在发生的事情。我不熟悉PhantomJS,也找不到任何合法的在线教程或指南来进行此设置。如果我不能完成这项工作,我会回到 iTextJFreeCharts

以下是我在 Spring 应用程序中使用的代码:

package my_spring_app.controller;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.phantomjs.PhantomJSDriverService;
import org.openqa.selenium.remote.Augmenter;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class MyController {

    protected final static Log logger = LogFactory
            .getLog(MyController.class);

    @RequestMapping(value = "/screenshot", method = RequestMethod.GET)
    public String showSupplementsPage(ModelMap model,
            HttpServletRequest request, HttpServletResponse response) {

        tryPhantom();

        return "screenshot";
    }

    private URI uri;
    private static PhantomJSDriverService service;
    private WebDriver webDriver;
    protected static DesiredCapabilities dCaps;

    public void tryPhantom() {

        service = new PhantomJSDriverService.Builder()
                .usingPhantomJSExecutable(new File("classpath:phantomjs.exe"))
                .usingAnyFreePort().build();
        try {
            service.start();
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            uri = new URI("http://localhost:8080/");
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        dCaps = new DesiredCapabilities();
        dCaps.setJavascriptEnabled(true);
        dCaps.setCapability("takesScreenshot", true);

        webDriver = new RemoteWebDriver(service.getUrl(), dCaps);
        webDriver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

        long iStart = System.currentTimeMillis();
        webDriver.get("http://localhost:8080/");

        webDriver = new Augmenter().augment(webDriver);
        File srcFile = ((TakesScreenshot) webDriver)
                .getScreenshotAs(OutputType.FILE);
        System.out.println("File:" + srcFile);
        try {
            FileUtils.copyFile(srcFile, new File("classpath:screenshots/pic.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("Single Page Time:"
                + (System.currentTimeMillis() - iStart));

        webDriver.quit();
        service.stop();
    }

}

这是我想到的图表:

【问题讨论】:

  • 我认为您对如何截取页面的屏幕截图有些困惑。我认为控制器可以渲染屏幕截图,但更优雅的方法是让不同的程序根据命令生成 pdf,然后通过控制器提供这些 pdf,如果这是你想要的,你不真的需要用java来做,用ruby做起来要简单得多。这是一个指南(cherpec.com/2013/04/30/capturing-web-page-screenshots-from-ruby
  • 如果我理解正确,我可以让控制器执行 Ruby 代码(?),然后屏幕截图将保存在类路径中,以供控制器再次读取以查看。我说的对吗?
  • 我认为最好只运行一次 ruby​​ 代码,因为生成所有屏幕截图需要时间。您可以让它预先生成您感兴趣的网页的所有屏幕截图。如果您确实需要动态生成屏幕截图,您应该在 JAVA 中定义。我认为如果你想要好的帮助,你需要描述你的需求更好。你想达到什么目标?
  • 是的,不幸的是它是动态的。我有一个表单结果页面(主要是报告),用户可以在其中选择以 PDF 格式输出。我想用flot.js 图表截取div 并将其粘贴到iText PDF 中,而不是在Java/iText 中重新进行。
  • 那我认为你做对了,虽然我认为你真的想让用户的电脑截屏是没有办法在 js 中做到这一点并将其发送到服务器?你正在尝试的将消耗相当多的 sdrvef 资源。虽然我认为它可以工作。请求也存在超时的风险。您遇到的 Tge 错误似乎与 phantom 无关,而且我认为您那里有很多库。我只使用了 selenium jar 并将其配置为使用 phantomjs 可执行文件。我认为下面的项目中我的 git hub PabloK 上可能有一个示例

标签: java spring selenium itext phantomjs


【解决方案1】:

我是否应该继续尝试这条路来获取我网站的屏幕截图? 我觉得这是一场失败的战斗。

你是对的,我认为管理依赖的方法需要重新考虑,否则将无法使站点正常工作。一个一个地手动下载 jars 不太可能产生好的结果,因为不能保证库版本相互兼容。

事实上,IncompatibleClassChangeError 表明下载的 jar 文件兼容。

最好的办法是使用 Maven 自动下载大部分 jar。通过仅声明顶级 jar,Maven 将自动下载所需的依赖 jar(传递依赖),帮助减少并在许多情况下消除库不兼容问题。

一旦站点启动并正常运行,只需在 Casper.js 中编写一些脚本以访问本地服务器中的页面、单击一些按钮以生成 PDF 等,然后拍摄一些快照。

Spring MVC 不需要特殊的集成,对于 Spring MVC 应用程序,如果该站点由 PhantomJS 或普通浏览器访问,它是透明的。

【讨论】:

  • 如何让 Spring 控制器访问 phatomjs.exe,因为我希望操作在那里?
猜你喜欢
  • 1970-01-01
  • 2016-01-01
  • 2014-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-24
  • 2013-06-15
相关资源
最近更新 更多