我想把我的混合应用程序的一些截图itunes自动连接。我正在运行Ubuntu 14.04. chromeDrive2.15.322448
使用Selenium和Xvfb自动截图很容易。但是要得到视网膜截图并不容易。
我用更高的dpi启动了我的Xvfb:
/usr/bin/Xvfb :99 -screen 0 2000x2000x24 -dpi 200
当我检查显示信息时,一切似乎都是正确的:
xdpyinfo -display :99
...
screen #0:
dimensions: 2000x2000 pixels (254x254 millimeters)
resolution: 200x200 dots per inch
depths (6): 24, 1, 4, 8, 16, 32
...
然后我像这样启动我的chromedriver
private WebDriver getChromeDriver ( Phone phone )
{
Map<String, Object> deviceMetrics = new HashMap<String, Object>();
deviceMetrics.put("width", 320);
deviceMetrics.put("height", 460);
deviceMetrics.put("pixelRatio", 2);
Map<String, Object> mobileEmulation = new HashMap<String, Object>();
mobileEmulation.put("deviceMetrics", deviceMetrics);
mobileEmulation.put("userAgent", "iphone4");
ChromeDriverService cds = new ChromeDriverService.Builder().withEnvironment(ImmutableMap.of("DISPLAY", ":99")).build();
Map<String, Object> chromeOptions = new HashMap<String, Object>();
chromeOptions.put("mobileEmulation", mobileEmulation);
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
capabilities.setCapability(ChromeOptions.CAPABILITY, chromeOptions);
WebDriver driver = new ChromeDriver(cds, capabilities);
return driver;
}
在完成了一些其他无聊的代码后,我截图:
File srcFile = ( (TakesScreenshot) driver ).getScreenshotAs(OutputType.FILE);
这不工作。屏幕截图是在普通的dpi。所以拍摄的网站图像只有320x460,而不是应有的640x960。
我在截图之前设置了一个断点,并像这样转储帧缓冲区:
export DISPLAY=:99
xwd -root -silent | xwdtopnm |pnmtojpeg > screen.jpg
如您所见,标题栏是根据更高的dpi呈现的,但浏览器窗口的其余部分没有。
那么,我如何运行一个具有更多dpi的Chrome驱动程序来拍摄视网膜截图呢?有可能吗?
我切换到Firefox,它通过以下代码为我工作。但目前情况并非如此,因为selenium在我的Firefox版本47上运行不正常,请参阅https://github.com/SeleniumHQ/selenium/issues/2257所以我现在无法测试这段代码,但上次我能够用它获得视网膜截图:
package de.kicktipp.screenshots.stackoverflow;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxBinary;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxProfile;
public class ScreenshotMaker
{
private PhoneList phoneList = new PhoneList();
private static final String HOST = "https://m.kicktipp.de";
private static final String PATH = "/";
private File resultDirectory;
private int filenumber = 0;
public static void main ( String[] args ) throws Exception
{
ScreenshotMaker screenshotMaker = new ScreenshotMaker();
screenshotMaker.run();
}
public WebDriver getDriver ( Phone phone, Display display )
{
FirefoxProfile profile = new FirefoxProfile();
// profile.setPreference("layout.css.devPixelsPerPx", "2.0");
// Ansonsten erscheint ein hässliches Popup welches Reader Funktion
// anbietet
profile.setPreference("reader.parse-on-load.enabled", false);
profile.setPreference("xpinstall.signatures.required", false);
FirefoxBinary firefoxBinary = new FirefoxBinary();
firefoxBinary.setEnvironmentProperty("DISPLAY", display.getDisplayNumberString());
FirefoxDriver firefoxDriver = new FirefoxDriver(firefoxBinary, profile);
firefoxDriver.manage().window().setSize(new Dimension(phone.getWidth(), display.getHeight()));
return firefoxDriver;
}
private void run ( ) throws Exception
{
mkdir();
for (Phone phone : phoneList)
{
WebDriver driver = null;
Display display = null;
try
{
display = new Display(phone.getDpiFaktor());
driver = getDriver(phone, display);
System.out.println(phone.getName());
filenumber = 0;
System.out.println("");
System.out.println("Generating Screenshots for " + phone.getName());
System.out.println("-----------------------------------------------------------------------------");
driver.get(HOST + "/");
shot(display, driver, PATH, phone);
}
finally
{
if (driver != null)
{
driver.quit();
}
if (display != null)
{
display.shutdown();
}
}
}
System.out.println("");
System.out.println("-----------------------------------------------------------------------------");
System.out.println("Finished.");
}
private void mkdir ( ) throws IOException
{
File targetDir = targetDir();
resultDirectory = new File(targetDir, "results");
resultDirectory.mkdir();
System.out.println("Writing screenshots to " + resultDirectory.getCanonicalPath());
}
public File targetDir ( )
{
String relPath = getClass().getProtectionDomain().getCodeSource().getLocation().getFile();
File targetDir = new File(relPath + "../..");
if (!targetDir.exists())
{
targetDir.mkdir();
}
return targetDir;
}
private void shot ( Display display, WebDriver driver, String path, Phone phoneSpec ) throws Exception
{
String url = getUrl(path);
driver.get(url);
scrollToRemoveScrollbars(driver);
// Selenium screenshot doesn't work, we are dumping the framebuffer
// directly
File srcFile = display.captureScreenshot();
moveFile(srcFile, phoneSpec);
}
private void scrollToRemoveScrollbars ( WebDriver driver ) throws Exception
{
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollTo(0,20);");
js.executeScript("window.scrollTo(0,0);");
Thread.sleep(800);
}
private String getUrl ( String path )
{
StringBuffer url = new StringBuffer(HOST);
url.append(path);
return url.toString();
}
private void moveFile ( File srcFile, Phone phone ) throws Exception
{
String filename = phone.getFilename(filenumber);
File file = new File(resultDirectory, filename);
if (file.exists())
{
file.delete();
}
crop(srcFile, file, phone);
System.out.println(filename);
}
private void crop ( File srcFile, File targetFile, Phone phone ) throws Exception
{
int width = phone.getPixelWidth();
int height = phone.getPixelHeight();
int yStart = 71 * phone.getDpiFaktor();
Image orig = ImageIO.read(srcFile);
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
bi.getGraphics().drawImage(orig, 0, 0, width, height, 0, yStart, width, height + yStart, null);
ImageIO.write(bi, "png", targetFile);
}
}
class PhoneList extends ArrayList<Phone>
{
private static final Phone IPHONE_4 = new Phone(320, 460, "iphone4", 2);
private static final Phone IPHONE_5 = new Phone(320, 548, "iphone5", 2);
private static final Phone IPHONE_6 = new Phone(375, 667, "iphone6", 2);
private static final Phone IPAD = new Phone(1024, 748, "ipad", 2);
private static final Phone IPHONE_6_PLUS = new Phone(414, 736, "iphone6plus", 3);
private static final Phone AMAZON = new Phone(480, 800, "amazon", 1);
public PhoneList ()
{
add(AMAZON);
add(IPHONE_4);
add(IPHONE_5);
add(IPHONE_6);
add(IPAD);
add(IPHONE_6_PLUS);
}
}
class Phone
{
private int width = 0;
private int height = 0;
private String name = "";
private int dpiFaktor = 2;
public Phone ( int width, int height, String name, int dpiFaktor )
{
this.width = width;
this.height = height;
this.name = name;
this.dpiFaktor = dpiFaktor;
}
public int getWidth ( )
{
return width;
}
public int getHeight ( )
{
return height;
}
public int getPixelWidth ( )
{
return width * dpiFaktor;
}
public int getPixelHeight ( )
{
return height * dpiFaktor;
}
public int getDpiFaktor ( )
{
return dpiFaktor;
}
public String getName ( )
{
return name;
}
public Dimension getDimension ( )
{
return new Dimension(width, height);
}
public String getFilename ( int number )
{
String dimension = getPixelWidth() + "x" + getPixelHeight();
return name + "-" + dimension + "-" + number + ".png";
}
}
class Display
{
private static final int HEIGHT = 5000;
private static final int WIDTH = 5000;
private static String XVFB = "/usr/bin/Xvfb";
private static String DISPLAY_NUMBER_STRING = ":99";
private static String SCREEN_SIZE = " -screen 0 " + WIDTH + "x" + HEIGHT + "x24";
private static String XVFB_COMMAND = XVFB + " " + DISPLAY_NUMBER_STRING + SCREEN_SIZE + " -dpi ";
private static int baseDpi = 100;
private Process p;
public Display ( int dpiFaktor ) throws IOException, InterruptedException
{
checkExecutable();
int dpi = baseDpi * dpiFaktor;
String cmd = XVFB_COMMAND + dpi;
p = Runtime.getRuntime().exec(cmd);
Thread.sleep(1000);
try
{
int exitValue = p.exitValue();
String msgTemplate = "ERROR: Exit Value: %s. Display konnte nicht gestartet werden. Läuft ein Display noch auf %s ?";
String msg = String.format(msgTemplate, exitValue, DISPLAY_NUMBER_STRING);
throw new IllegalStateException(msg);
}
catch (IllegalThreadStateException e)
{
// Das ist gut, der Prozess ist noch nicht beendet.
System.out.println("Switched on display at " + dpi + "dpi with command " + cmd);
return;
}
}
private void checkExecutable ( )
{
File file = new File(XVFB);
if (!file.canExecute())
{
System.err.println("Xvfb is not installed at " + XVFB);
System.err.println("Install Xvfb by runing");
System.err.println("apt-get install xvfb");
}
}
public File captureScreenshot ( ) throws IOException, InterruptedException
{
File tempFile = File.createTempFile("screenshots", ".png");
String absolutePath = tempFile.getAbsolutePath();
String cmd = "import -window root " + absolutePath;
String[] env = new String[] { "DISPLAY=" + DISPLAY_NUMBER_STRING };
Process exec = Runtime.getRuntime().exec(cmd, env);
exec.waitFor();
return tempFile;
}
public void shutdown ( ) throws IOException, InterruptedException
{
p.destroy();
try
{
Thread.sleep(1000);
int exitValue = p.exitValue();
System.out.println("Display was switched off. ExitValue: " + exitValue);
}
catch (IllegalThreadStateException e)
{
// Das ist nicht gut, der Prozess sollte beendet sein.
// Kill it:
p = Runtime.getRuntime().exec("pkill Xvfb");
}
}
public String getDisplayNumberString ( )
{
return DISPLAY_NUMBER_STRING;
}
public int getHeight ( )
{
return HEIGHT;
}
}
这是我的pom:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.kicktipp</groupId>
<artifactId>screenshots</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>screenshots</name>
<properties>
<jdk.version>1.7</jdk.version>
<maven.version>3.0</maven.version>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<selenium-java.version>2.53.1</selenium-java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>${selenium-java.version}</version>
</dependency>
</dependencies>
</project>
我面临着同样的问题,但仍然无法解决,但下面的内容可能会有用。它允许我通过将VNC连接连接到xvfb帧缓冲区来排除xvfb或chrome。
#!/bin/bash
export GEOMETRY="$SCREEN_WIDTH""x""$SCREEN_HEIGHT""x""$SCREEN_DEPTH"
function shutdown {
kill -s SIGTERM $NODE_PID
wait $NODE_PID
}
sudo -E -i -u seluser \
DISPLAY=$DISPLAY \
xvfb-run --server-args="$DISPLAY -screen 0 $GEOMETRY -dpi 300 -ac +extension RANDR" \
java -jar /opt/selenium/selenium-server-standalone.jar &
NODE_PID=$!
trap shutdown SIGTERM SIGINT
for i in $(seq 1 10)
do
xdpyinfo -display $DISPLAY >/dev/null 2>&1
if [ $? -eq 0 ]; then
break
fi
echo Waiting xvfb...
sleep 0.5
done
fluxbox -display $DISPLAY &
x11vnc -forever -usepw -shared -rfbport 5900 -display $DISPLAY &
wait $NODE_PID
输入VNC'ing后,可以从终端加载googlechrome
GUI。网页导航确认Chrome使用正确的DPI呈现网页。截图http://i.stack.imgur.com/iEjo0.jpg
我真的很想让这个工作,所以如果你有任何新的发展,请联系。我用https://registry.hub.docker.com/u/selenium/standalone-chrome-debug/BTW。
如果你只想拍摄一些屏幕主机,你可以使用谷歌chrome无头工具。例如,获取视网膜屏幕截图就像
$ google-chrome --headless --hide-scrollbars --disable-gpu \
--screenshot --force-device-scale-factor=2 \
--window-size=750,1334 https://www.kicktipp.de/
我需要使用Sikuli的自动化,但我无法采取截图。问题是,当我点击“截屏”或“创建区域”时,IDE会被隐藏,但选择区域选项不会出现....
问题内容: 我要实现的是从python中的任何网站获取网站截图。 环境:Linux 问题答案: 在Mac上,有webkit2png,在Linux+KDE上,可以使用khtml2png。我已经尝试了前者,并且效果很好,并且听说后者已投入使用。 我最近遇到了QtWebKit,它声称是跨平台的(我猜Qt将WebKit卷入了他们的库中)。但是我从未尝试过,所以我无法告诉您更多信息。 QtWebKit链接显
可在游戏中等拍摄并保存任何场景。同时按下PS键和START键。 可从(照片)查看已保存的信息。 若要拍摄画面截图,需事先将PS Vita专用存储卡插入主机。 因画面或应用程序的状态,可能无法拍摄画面截图。
问题内容: 我正在构建一个称为“ HTML测验”的东西。它完全在JavaScript上运行,非常酷。 最后,弹出一个结果框,显示“您的结果:”,它显示了他们花费了多少时间,他们得到了多少百分比以及他们从10个问题中得出了多少个问题。我想有一个按钮,上面写着“捕获结果”,并使其以某种方式截取屏幕截图或div,然后仅在页面上显示捕获的图像即可在其中单击鼠标右键并“将图像另存为”。 我真的很想这样做,以
问题内容: 我正在尝试使用WebdriverIO截取整个页面的屏幕截图。 我读过,最好的方法是使用WebdriverCSS增强我的WebdriverIO流。WebdriverCSS自动截图整个页面? 问题是WebdriverCSS对我不起作用。我认为是因为它尚未与兼容。 有什么办法可以使它起作用,或者可以使用其他解决方案? 我的代码: ( 这是生产什么,但在回调中未定义的值 ) !EDIT: 这是
嗨,我如何在Windows电脑上使用任何浏览器拍摄网页的完整屏幕截图? 每当我用PrintScreen截图时,它只截图显示页面,但我希望截图的高度为整页。我们能拍完整的截图吗,包括隐藏的八张? 抱歉我英语不好。 我有firefox和chrome。