目前我正在尝试使用Selenium WebDriver捕获屏幕截图。但我只能获得整页屏幕截图。但是,我想要的只是捕获页面的一部分,或者只是基于ID或任何特定元素定位器捕获特定元素。 (例如,我希望用图像id =“Butterfly”捕获图片)
有没有办法按选定的项目或元素捕获屏幕截图?
答案 0 :(得分:97)
我们可以通过裁剪整个页面截图来获取元素截图,如下所示:
driver.get("http://www.google.com");
WebElement ele = driver.findElement(By.id("hplogo"));
// Get entire page screenshot
File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
BufferedImage fullImg = ImageIO.read(screenshot);
// Get the location of element on the page
Point point = ele.getLocation();
// Get width and height of the element
int eleWidth = ele.getSize().getWidth();
int eleHeight = ele.getSize().getHeight();
// Crop the entire page screenshot to get only element screenshot
BufferedImage eleScreenshot= fullImg.getSubimage(point.getX(), point.getY(),
eleWidth, eleHeight);
ImageIO.write(eleScreenshot, "png", screenshot);
// Copy the element screenshot to disk
File screenshotLocation = new File("C:\\images\\GoogleLogo_screenshot.png");
FileUtils.copyFile(screenshot, screenshotLocation);
答案 1 :(得分:10)
在Node.js
中,我编写了以下代码,但它不是基于selenium的官方WebDriverJS,而是基于SauceLabs's WebDriver
:WD.js和非常紧凑的图像名为EasyImage的图书馆。
我只想强调你不能真正拍摄元素的截图,但你应该做的是首先,截取整个页面的截图,然后选择你喜欢的页面部分并裁剪该特定部分:< / p>
browser.get(URL_TO_VISIT)
.waitForElementById(dependentElementId, webdriver.asserters.isDisplayed, 3000)
.elementById(elementID)
.getSize().then(function(size) {
browser.elementById(elementID)
.getLocation().then(function(location) {
browser.takeScreenshot().then(function(data) {
var base64Data = data.replace(/^data:image\/png;base64,/, "");
fs.writeFile(filePath, base64Data, 'base64', function(err) {
if (err) {
console.log(err);
}
else {
cropInFile(size, location, filePath);
}
doneCallback();
});
});
});
});
cropInFileFunction就像这样:
var cropInFile = function(size, location, srcFile) {
easyimg.crop({
src: srcFile,
dst: srcFile,
cropwidth: size.width,
cropheight: size.height,
x: location.x,
y: location.y,
gravity: 'North-West'
},
function(err, stdout, stderr) {
if (err) throw err;
});
};
答案 2 :(得分:8)
答案 3 :(得分:5)
这是使用Selenium Webdriver和Pillow的Python 3版本。 该程序捕获整个页面的屏幕快照,并根据其位置裁剪元素。元素图片将以image.png
的形式提供from selenium import webdriver
from PIL import Image
driver = webdriver.Chrome()
driver.get('https://www.google.co.in')
element = driver.find_element_by_id("lst-ib")
location = element.location
size = element.size
driver.save_screenshot("shot.png")
x = location['x']
y = location['y']
w = size['width']
h = size['height']
width = x + w
height = y + h
im = Image.open('shot.png')
im = im.crop((int(x), int(y), int(width), int(height)))
im.save('image.png')
答案 4 :(得分:4)
我浪费了很多时间拍摄截图,我想保存你的截图。 我用过chrome + selenium + c#结果非常可怕。最后我写了一个函数:
driver.Manage().Window.Maximize();
RemoteWebElement remElement = (RemoteWebElement)driver.FindElement(By.Id("submit-button"));
Point location = remElement.LocationOnScreenOnceScrolledIntoView;
int viewportWidth = Convert.ToInt32(((IJavaScriptExecutor)driver).ExecuteScript("return document.documentElement.clientWidth"));
int viewportHeight = Convert.ToInt32(((IJavaScriptExecutor)driver).ExecuteScript("return document.documentElement.clientHeight"));
driver.SwitchTo();
int elementLocation_X = location.X;
int elementLocation_Y = location.Y;
IWebElement img = driver.FindElement(By.Id("submit-button"));
int elementSize_Width = img.Size.Width;
int elementSize_Height = img.Size.Height;
Size s = new Size();
s.Width = driver.Manage().Window.Size.Width;
s.Height = driver.Manage().Window.Size.Height;
Bitmap bitmap = new Bitmap(s.Width, s.Height);
Graphics graphics = Graphics.FromImage(bitmap as Image);
graphics.CopyFromScreen(0, 0, 0, 0, s);
bitmap.Save(filePath, System.Drawing.Imaging.ImageFormat.Png);
RectangleF part = new RectangleF(elementLocation_X, elementLocation_Y + (s.Height - viewportHeight), elementSize_Width, elementSize_Height);
Bitmap bmpobj = (Bitmap)Image.FromFile(filePath);
Bitmap bn = bmpobj.Clone(part, bmpobj.PixelFormat);
bn.Save(finalPictureFilePath, System.Drawing.Imaging.ImageFormat.Png);
答案 5 :(得分:4)
对于每个要求C#代码的人,下面是我的实现的简化版本。
public static void TakeScreenshot(IWebDriver driver, IWebElement element)
{
try
{
string fileName = DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + ".jpg";
Byte[] byteArray = ((ITakesScreenshot)driver).GetScreenshot().AsByteArray;
System.Drawing.Bitmap screenshot = new System.Drawing.Bitmap(new System.IO.MemoryStream(byteArray));
System.Drawing.Rectangle croppedImage = new System.Drawing.Rectangle(element.Location.X, element.Location.Y, element.Size.Width, element.Size.Height);
screenshot = screenshot.Clone(croppedImage, screenshot.PixelFormat);
screenshot.Save(String.Format(@"C:\SeleniumScreenshots\" + fileName, System.Drawing.Imaging.ImageFormat.Jpeg));
}
catch (Exception e)
{
logger.Error(e.StackTrace + ' ' + e.Message);
}
}
答案 6 :(得分:2)
Surya's answer效果很好。如果你不愿意,那么这种方法对你来说可能更好
private Image getScreenshot(final WebDriver d, final WebElement e) throws IOException {
final BufferedImage img;
final Point topleft;
final Point bottomright;
final byte[] screengrab;
screengrab = ((TakesScreenshot) d).getScreenshotAs(OutputType.BYTES);
img = ImageIO.read(new ByteArrayInputStream(screengrab));
//crop the image to focus on e
//get dimensions (crop points)
topleft = e.getLocation();
bottomright = new Point(e.getSize().getWidth(),
e.getSize().getHeight());
return img.getSubimage(topleft.getX(),
topleft.getY(),
bottomright.getX(),
bottomright.getY());
}
如果您愿意,可以跳过声明screengrab
而不是
img = ImageIO.read(
new ByteArrayInputStream(
((TakesScreenshot) d).getScreenshotAs(OutputType.BYTES)));
哪个更干净,但为了清晰起见我把它留了下来。然后,您可以save it as a file或put it in a JPanel了解您的内容。
答案 7 :(得分:2)
public void GenerateSnapshot(string url, string selector, string filePath)
{
using (IWebDriver driver = new ChromeDriver())
{
driver.Navigate().GoToUrl(url);
var remElement = driver.FindElement(By.CssSelector(selector));
Point location = remElement.Location;
var screenshot = (driver as ChromeDriver).GetScreenshot();
using (MemoryStream stream = new MemoryStream(screenshot.AsByteArray))
{
using (Bitmap bitmap = new Bitmap(stream))
{
RectangleF part = new RectangleF(location.X, location.Y, remElement.Size.Width, remElement.Size.Height);
using (Bitmap bn = bitmap.Clone(part, bitmap.PixelFormat))
{
bn.Save(filePath, System.Drawing.Imaging.ImageFormat.Png);
}
}
}
driver.Close();
}
}
答案 8 :(得分:2)
我认为这里的大多数答案都过度设计了。我这样做的方法是通过 2 个辅助方法,第一个等待基于任何选择器的元素;第二个截图。
注意:我们将 WebElement
转换为 TakesScreenshot
实例,因此我们只在图像中专门捕获该元素。如果您想要完整的页面/窗口,则应改为使用 driver
。
WebDriver driver = new FirefoxDriver(); // define this somewhere (or chrome etc)
public <T> T screenshotOf(By by, long timeout, OutputType<T> type) {
return ((TakesScreenshot) waitForElement(by, timeout))
.getScreenshotAs(type);
}
public WebElement waitForElement(By by, long timeout) {
return new WebDriverWait(driver, timeout)
.until(driver -> driver.findElement(by));
}
然后像这样截取任何你想要的截图:
long timeout = 5; // in seconds
/* Screenshot (to file) based on first occurence of tag */
File sc = screenshotOf(By.tagName("body"), timeout, OutputType.FILE);
/* Screenshot (in memory) based on CSS selector (e.g. first image in body
who's "src" attribute starts with "https") */
byte[] sc = screenshotOf(By.cssSelector("body > img[href^='https']"), timeout, OutputType.BYTES);
答案 9 :(得分:2)
这是C#的扩展函数:
public static BitmapImage GetElementImage(this IWebDriver webDriver, By by)
{
var elements = webDriver.FindElements(by);
if (elements.Count == 0)
return null;
var element = elements[0];
var screenShot = (webDriver as ITakesScreenshot).GetScreenshot();
using (var ms = new MemoryStream(screenShot.AsByteArray))
{
Bitmap screenBitmap;
screenBitmap = new Bitmap(ms);
return screenBitmap.Clone(
new Rectangle(
element.Location.X,
element.Location.Y,
element.Size.Width,
element.Size.Height
),
screenBitmap.PixelFormat
).ToBitmapImage();
}
}
现在你可以用它来拍摄这样的任何元素的图像:
var image = webDriver.GetElementImage(By.Id("someId"));
答案 10 :(得分:1)
在Selenium中为特定元素拍摄快照的功能之下。这里的驱动程序是一种WebDriver。
<div style="float:right ; position:relative; top: -145px ; right:8px;">
<table>
<tr>
<td><p align="left"><strong>Where the good ideas come from?</strong></p></td>
</tr>
<tr>
<td> <iframe src="images/videos.mp4" width="280" height="240" align="right"></iframe> </td>
</tr>
</table>
</div>
</div>
答案 11 :(得分:1)
如果您正在寻找JavaScript解决方案,请参阅我的要点:
https://gist.github.com/sillicon/4abcd9079a7d29cbb53ebee547b55fba
基本思路是一样的,首先拍摄屏幕截图,然后裁剪。 但是,我的解决方案不需要其他库,只需要纯WebDriver API代码。但是,副作用是它可能会增加测试浏览器的负载。
答案 12 :(得分:1)
考虑使用针 - 工具进行自动视觉比较 https://github.com/bfirsh/needle, 它具有内置功能,可以截取特定元素的截图(由CSS选择器选择)。该工具适用于Selenium的WebDriver,它是用Python编写的。
答案 13 :(得分:0)
using System.Drawing;
using System.Drawing.Imaging;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
public void ScreenshotByElement()
{
IWebDriver driver = new FirefoxDriver();
String baseURL = "www.google.com/"; //url link
String filePath = @"c:\\img1.png";
driver.Navigate().GoToUrl(baseURL);
var remElement = driver.FindElement(By.Id("Butterfly"));
Point location = remElement.Location;
var screenshot = (driver as FirefoxDriver).GetScreenshot();
using (MemoryStream stream = new MemoryStream(screenshot.AsByteArray))
{
using (Bitmap bitmap = new Bitmap(stream))
{
RectangleF part = new RectangleF(location.X, location.Y, remElement.Size.Width, remElement.Size.Height);
using (Bitmap bn = bitmap.Clone(part, bitmap.PixelFormat))
{
bn.Save(filePath, ImageFormat.Png);
}
}
}
}
答案 14 :(得分:0)
如果您在Chrome浏览器中出现异常 java.awt.image.RasterFormatException ,或者您想将某个元素滚动到视图中,然后捕获屏幕截图。
这是@Surya答案中的解决方案。
JavascriptExecutor jsExecutor = (JavascriptExecutor) driver;
Long offsetTop = (Long) jsExecutor.executeScript("window.scroll(0, document.querySelector(\""+cssSelector+"\").offsetTop - 0); return document.querySelector(\""+cssSelector+"\").getBoundingClientRect().top;");
WebElement ele = driver.findElement(By.cssSelector(cssSelector));
// Get entire page screenshot
File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
BufferedImage fullImg = ImageIO.read(screenshot);
// Get the location of element on the page
Point point = ele.getLocation();
// Get width and height of the element
int eleWidth = ele.getSize().getWidth();
int eleHeight = ele.getSize().getHeight();
// Crop the entire page screenshot to get only element screenshot
BufferedImage eleScreenshot= fullImg.getSubimage(point.getX(), Math.toIntExact(offsetTop),
eleWidth, eleHeight);
ImageIO.write(eleScreenshot, "png", screenshot);
// Copy the element screenshot to disk
File screenshotLocation = new File("c:\\temp\\div_element_1.png");
FileUtils.copyFile(screenshot, screenshotLocation);
答案 15 :(得分:0)
c#代码:
public Bitmap MakeElemScreenshot( IWebDriver driver, WebElement elem)
{
Screenshot myScreenShot = ((ITakesScreenshot)driver).GetScreenshot();
Bitmap screen = new Bitmap(new MemoryStream(myScreenShot.AsByteArray));
Bitmap elemScreenshot = screen.Clone(new Rectangle(elem.Location, elem.Size), screen.PixelFormat);
screen.Dispose();
return elemScreenshot;
}
答案 16 :(得分:0)
Python 3
尝试使用硒3.141.0和chromedriver 73.0.3683.68,
from selenium import webdriver
chromedriver = '/usr/local/bin/chromedriver'
chromeOptions = webdriver.ChromeOptions()
chromeOptions.add_argument('window-size=1366x768')
chromeOptions.add_argument('disable-extensions')
cdriver = webdriver.Chrome(options=chromeOptions, executable_path=chromedriver)
cdriver.get('url')
element = cdriver.find_element_by_css_selector('.some-css.selector')
element.screenshot_as_png('elemenent.png')
无需获取完整图像并获得全屏图像的一部分。
创建Rohit's answer时可能不可用。
答案 17 :(得分:0)
这是我的版本,在C#中,我基本上从Brook的答案中得到了大部分,并对其进行了修改以适合我的目的
public static byte[] GetElementImage(this IWebElement element)
{
var screenShot = MobileDriver.Driver.GetScreenshot();
using (var stream = new MemoryStream(screenShot.AsByteArray))
{
var screenBitmap = new Bitmap(stream);
var elementBitmap = screenBitmap.Clone(
new Rectangle(
element.Location.X,
element.Location.Y,
element.Size.Width,
element.Size.Height
),
screenBitmap.PixelFormat
);
var converter = new ImageConverter();
return (byte[]) converter.ConvertTo(elementBitmap, typeof(byte[]));
}
}
答案 18 :(得分:0)
要截取特定元素的屏幕截图,您现在可以使用以下命令:
public void takeCanvasScreenshot(WebElement element, String imageName) {
File screenshot = element.getScreenshotAs(OutputType.FILE);
try {
FileUtils.copyFile(screenshot, new File("src/main/resources/screenshots/" + imageName + ".png"));
} catch (IOException e) {
e.printStackTrace();
}
}
答案 19 :(得分:0)
对于 C#,下面的代码可以工作。
试试
{
IWebElement 事务 = driver.FindElement(By.XPath(".///*[@id='some element']"));
截图截图 = ((ITakesScreenshot)driver).GetScreenshot();
string title = "某个标题";
screenshot.SaveAsFile(title, ScreenshotImageFormat.Jpeg);
} 捕获(异常) {
// 元素未找到时处理
}
答案 20 :(得分:-1)
我相信当你使用C#并且我的解决方案包含一个Java库时,这对你不起作用,但也许其他人会发现它有用。
要捕获自定义屏幕截图,您可以使用Shutterbug库。为此目的的具体要求是:
compile 'org.xwalk:xwalk_core_library:22.52.561.4'
答案 21 :(得分:-1)
我遵循了@codeslord的示例代码,但是由于某些原因,我不得不以不同的方式访问我的屏幕截图数据:
# Open the Firefox webdriver
driver = webdriver.Firefox()
# Find the element that you're interested in
imagepanel = driver.find_element_by_class_name("panel-height-helper")
# Access the data bytes for the web element
datatowrite = imagepanel.screenshot_as_png
# Write the byte data to a file
outfile = open("imagepanel.png", "wb")
outfile.write(datatowrite)
outfile.close()
(使用Python 3.7,Selenium 3.141.0和Mozilla Geckodriver 71.0.0.7222)
答案 22 :(得分:-2)
我使用@ Brook的答案的修改版本,即使对于需要滚动页面的元素也能正常工作。
public void TakeScreenshot(string fileNameWithoutExtension, IWebElement element)
{
// Scroll to the element if necessary
var actions = new Actions(_driver);
actions.MoveToElement(element);
actions.Perform();
// Get the element position (scroll-aware)
var locationWhenScrolled = ((RemoteWebElement) element).LocationOnScreenOnceScrolledIntoView;
var fileName = fileNameWithoutExtension + ".png";
var byteArray = ((ITakesScreenshot) _driver).GetScreenshot().AsByteArray;
using (var screenshot = new System.Drawing.Bitmap(new System.IO.MemoryStream(byteArray)))
{
var location = locationWhenScrolled;
// Fix location if necessary to avoid OutOfMemory Exception
if (location.X + element.Size.Width > screenshot.Width)
{
location.X = screenshot.Width - element.Size.Width;
}
if (location.Y + element.Size.Height > screenshot.Height)
{
location.Y = screenshot.Height - element.Size.Height;
}
// Crop the screenshot
var croppedImage = new System.Drawing.Rectangle(location.X, location.Y, element.Size.Width, element.Size.Height);
using (var clone = screenshot.Clone(croppedImage, screenshot.PixelFormat))
{
clone.Save(fileName, ImageFormat.Png);
}
}
}
两个if
是必要的(至少对于Chrome驱动程序而言),因为当需要滚动时,裁剪的大小超过屏幕截图大小的1个像素。