项目有个小功能:为指定文章生成一份分享海报,看到WordPress的海报插件按捺不住了开工了。这里主要讲使用selenium框架来实现,不讲其它方案或框架。开动吧
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-firefox-driver -->
org.seleniumhq.selenium
selenium-firefox-driver
3.141.59
@Test
public void savesreen() throws IOException {
//有问题的代码不要复制使用
WebDriver driver = new FirefoxDriver();
driver.get("http://www.test.com/topic/poster?topic=91");
WebElement ele = driver.findElement(By.id("poster")); //driver.findElement(By.tagName("body"));
Rectangle rect = ele.getRect();
// Get entire page screenshot
File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
BufferedImage fullImg = ImageIO.read(screenshot);
BufferedImage eleScreenshot= fullImg.getSubimage(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
File posterShot = File.createTempFile("20191219", "png");
ImageIO.write(eleScreenshot, "png", posterShot);
// Copy the element screenshot to disk
File screenshotLocation = new File("C:\\qq_screenshot.png");
FileUtils.copyFile(posterShot, screenshotLocation);
driver.quit();
}
以上代码是有问题,不要复制使用,为哈要写呢?主要是讲下面的异常:
java.lang.IllegalStateException: The path to the driver executable must be set by the webdriver.gecko.driver system property; for more information, see https://github.com/mozilla/geckodriver. The latest version can be downloaded from https://github.com/mozilla/geckodriver/releases
at com.google.common.base.Preconditions.checkState(Preconditions.java:847)
at org.openqa.selenium.remote.service.DriverService.findExecutable(DriverService.java:134)
at org.openqa.selenium.firefox.GeckoDriverService.access$100(GeckoDriverService.java:44)
at org.openqa.selenium.firefox.GeckoDriverService$Builder.findDefaultExecutable(GeckoDriverService.java:167)
at org.openqa.selenium.remote.service.DriverService$Builder.build(DriverService.java:355)
at org.openqa.selenium.firefox.FirefoxDriver.toExecutor(FirefoxDriver.java:190)
at org.openqa.selenium.firefox.FirefoxDriver.<init>(FirefoxDriver.java:147)
at org.openqa.selenium.firefox.FirefoxDriver.<init>(FirefoxDriver.java:125)
...
异常是说需要调置一个系统参数:webdriver.gecko.driver, 参数指向的文件可以去https://github.com/mozilla/geckodriver下载。好去下载并设置
@Test
public void savesreen() throws IOException {
//有问题的代码不要复制使用
System.setProperty("webdriver.gecko.driver","C:\\geckodriver-v0.26.0\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
//ETC 其它代码不动
}
需要注意的是配合firefox的版本与selenium的版本,这个在//firefox-source-docs.mozilla.org/testing/geckodriver/有说明。
org.openqa.selenium.WebDriverException: Timed out waiting 45 seconds for Firefox to start.
Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03'
System info: host: 'DESKTOP-QTAURUN', ip: '10.0.0.4', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '1.8.0_231'
Driver info: driver.version: FirefoxDriver
at org.openqa.selenium.firefox.XpiDriverService.waitUntilAvailable(XpiDriverService.java:247)
at org.openqa.selenium.firefox.XpiDriverService.start(XpiDriverService.java:159)
at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:79)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552)
at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:213)
at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:131)
at org.openqa.selenium.firefox.FirefoxDriver.<init>(FirefoxDriver.java:147)
at org.openqa.selenium.firefox.FirefoxDriver.<init>(FirefoxDriver.java:125)
也有可能出现这个异常,可能你是从网上复制的以下代码
System.setProperty(“webdriver.firefox.marionette”,“C:\geckodriver-v0.26.0\geckodriver.exe”);
这里提示一下多看错误提示,不要盲目复制。正常时RUN后会打开Firefox浏览器,浏览器的地址栏上会有get的URL.
卡在W3C这,一直没有继续下去。一下午的反复运行发现总结有可能这几种情况
File screenshotLocation = new File(“C:\qq_screenshot.png”);
windows 10 可能对C盘有权限限制。
例:原图的高度只有700多px, 而截取的y坐标大于700
先看可以用的代码:
@Test
public void savesreen() throws IOException {
System.setProperty("webdriver.gecko.driver","C:\\geckodriver-v0.26.0\\geckodriver.exe");
//
FirefoxOptions options = new FirefoxOptions().setProfile(new FirefoxProfile());
WebDriver driver = new FirefoxDriver(options);
driver.manage().window().setSize(new Dimension(1920,1200)); //new Dimension(1024,768)|new Dimension(1440,900)
//
driver.get("http://www.test.com/topic/poster?topic=91");
WebElement ele = driver.findElement(By.id("poster"));
Rectangle rect = ele.getRect();
System.out.println("coordinate x: "+rect.getX()+", coordinate y: "+rect.getY());
System.out.println("Rectangle width: "+rect.getWidth()+", Rectangle height: "+rect.getHeight());
// Get entire page screenshot
File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
BufferedImage fullImg = ImageIO.read(screenshot);
BufferedImage eleScreenshot= fullImg.getSubimage(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
File posterShot = File.createTempFile("20191219", "png");
ImageIO.write(eleScreenshot, "png", posterShot);
// Copy the element screenshot to disk
File screenshotLocation = new File("C:\\home\\admin\\qq_screenshot.png");
FileUtils.copyFile(posterShot, screenshotLocation);
driver.quit();
}
driver.manage().window().setSize(new Dimension(1920,1200));
可以看到后面的注释有
//new Dimension(1024,768)|new Dimension(1440,900)
我发现这两个分辨率即使在截整屏时海报都显示不全,更合况在截取元素时图片也是不全的。在1920x1200时生成的整屏图片的比率为
运行代码后控制的显示如下:
#poster宽和高的值在浏览器浏览是正确的,但看这个整屏的图的大小都能猜到起码的左上角的起始作坐肯定是错的
哪如何知道左上角的起始坐标呢,实际操作可以通过window的画图软件中打开图片都能知道
使用以下的代码都可以截取正确的元素截图
BufferedImage eleScreenshot= fullImg.getSubimage(818, 138, 750, 1072);
这都难堪了,怎么通过程序算出左上角的起始作标?怎么通过程序算出在指定窗口中的实际元素的宽和高?