【发布时间】: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.jarcglib-3.1.jarcommons-exec-1.2.jarguava-16.0.1.jarhttpclient-4.3.2.jarhttpcore-4.3.2.jarjson-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,也找不到任何合法的在线教程或指南来进行此设置。如果我不能完成这项工作,我会回到 iText 和 JFreeCharts。
以下是我在 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并将其粘贴到iTextPDF 中,而不是在Java/iText 中重新进行。 -
那我认为你做对了,虽然我认为你真的想让用户的电脑截屏是没有办法在 js 中做到这一点并将其发送到服务器?你正在尝试的将消耗相当多的 sdrvef 资源。虽然我认为它可以工作。请求也存在超时的风险。您遇到的 Tge 错误似乎与 phantom 无关,而且我认为您那里有很多库。我只使用了 selenium jar 并将其配置为使用 phantomjs 可执行文件。我认为下面的项目中我的 git hub PabloK 上可能有一个示例
标签: java spring selenium itext phantomjs