現在、SeleniumWebDriverを使用してスクリーンショットをキャプチャしようとしています。しかし、私はページ全体のスクリーンショットしか取得できません。ただし、私が望んでいたのは、ページの一部をキャプチャすること、またはIDや特定の要素ロケーターに基づいて特定の要素だけをキャプチャすることです。(たとえば、image id = "Butterfly"で写真をキャプチャしたい)
選択したアイテムまたは要素ごとにスクリーンショットをキャプチャする方法はありますか?
現在、SeleniumWebDriverを使用してスクリーンショットをキャプチャしようとしています。しかし、私はページ全体のスクリーンショットしか取得できません。ただし、私が望んでいたのは、ページの一部をキャプチャすること、またはIDや特定の要素ロケーターに基づいて特定の要素だけをキャプチャすることです。(たとえば、image id = "Butterfly"で写真をキャプチャしたい)
選択したアイテムまたは要素ごとにスクリーンショットをキャプチャする方法はありますか?
回答:
以下のようにページ全体のスクリーンショットを切り抜くことで、要素のスクリーンショットを取得できます。
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);
これは、SeleniumWebdriverとPillowを使用したPython3バージョンです。このプログラムは、ページ全体のスクリーンショットをキャプチャし、その場所に基づいて要素をトリミングします。要素画像はimage.pngとして利用可能になります。Firefoxは、element.screenshot_as_png( 'image_name')を使用して要素画像を直接保存することをサポートしています。
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')
更新
現在、chromeは個々の要素のスクリーンショットもサポートしています。したがって、以下に示すように、Web要素のスクリーンショットを直接キャプチャすることができます。
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://www.google.co.in')
image = driver.find_element_by_id("lst-ib").screenshot_as_png
# or
# element = driver.find_element_by_id("lst-ib")
# element.screenshot_as_png("image.png")
element.size
によって作成されたスクリーンショットdriver.save_screenshot
はピクセルの寸法を持っているのに対し、私はそれがポイントで与えられていると確信しています。画面が1以外のピクセル・ツー・ポイントの比率がある場合(例えば、網膜のMacBookには、ポイントごとに2つのピクセルを持っている- 2の比率を)あなたは、乗算に必要w
とh
その比で。
from StringIO import StringIO; from PIL import Image; img = Image.open(StringIO(image))
import io; from PIL import Image; img = Image.open(io.BytesIO(image)); img.save("image.png")
でNode.js
、私は動作しますが、それはセレンの公式WebDriverJSに基づいていますが、に基づいていない次のコードを書いたSauceLabs's WebDriver
:WD.jsと呼ばれる非常にコンパクトなイメージライブラリEasyImageを。
要素のスクリーンショットを実際に撮ることはできないことを強調したいのですが、最初にページ全体のスクリーンショットを撮り、次にページの好きな部分を選択して、その特定の部分をトリミングする必要があります。
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;
});
};
YandexのASHOTフレームワークは、SeleniumWebDriverスクリプトでスクリーンショットを撮るために使用できます。
このフレームワークはhttps://github.com/yandex-qatools/ashotにあります。
スクリーンショットを撮るためのコードは非常に簡単です:
ページ全体
screenshot = new AShot().shootingStrategy(
new ViewportPastingStrategy(1000)).takeScreenshot(driver);
ImageIO.write(screenshot.getImage(), "PNG", new File("c:\\temp\\results.png"));
特定のWeb要素
screenshot = new AShot().takeScreenshot(driver,
driver.findElement(By.xpath("(//div[@id='ct_search'])[1]")));
ImageIO.write(screenshot.getImage(), "PNG", new File("c:\\temp\\div_element.png"));
.shootingStrategy(ShootingStrategies.viewportPasting(100))
とあまりにSPECIFIC WEB ELEMENT
モード、またはそれは、すべての要素をキャプチャしない場合があります。
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);
}
}
スクリーンショットを撮るのに多くの時間を無駄にしました。あなたのスクリーンショットを保存したいと思います。私はクロム+セレン+ 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);
ディスクIOを使用してもかまわない場合は、Suryaの回答が役立ちます。望まない場合は、この方法の方が適している可能性があります
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)));
これはよりクリーンですが、わかりやすくするためにそのままにしておきました。その後、ファイルとして保存するか、JPanelに心ゆくまで入れることができます。
Python 3
Selenium3.141.0とchromedriver73.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の回答が作成されたとき、これは利用できなかった可能性があります。
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();
}
}
JavaScriptソリューションをお探しの場合は、ここに私の要点があります。
https://gist.github.com/sillicon/4abcd9079a7d29cbb53ebee547b55fba
基本的な考え方は同じです。最初にスクリーンショットを撮り、次にトリミングします。ただし、私のソリューションでは他のライブラリは必要なく、純粋なWebDriverAPIコードのみが必要です。ただし、副作用として、テストブラウザの負荷が増加する可能性があります。
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"));
自動視覚比較用の針ツールhttps://github.com/bfirsh/needleの使用を検討して ください。これには、特定の要素のスクリーンショットを撮ることができる機能が組み込まれています(CSSセレクターによって選択されます)。このツールはSeleniumのWebDriverで動作し、Pythonで記述されています。
Seleniumの特定の要素のスナップショットを取得するための関数の下。ここで、ドライバーはWebDriverの一種です。
private static void getScreenshot(final WebElement e, String fileName) throws IOException {
final BufferedImage img;
final Point topleft;
final Point bottomright;
final byte[] screengrab;
screengrab = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
img = ImageIO.read(new ByteArrayInputStream(screengrab));
topleft = e.getLocation();
bottomright = new Point(e.getSize().getWidth(), e.getSize().getHeight());
BufferedImage imgScreenshot=
(BufferedImage)img.getSubimage(topleft.getX(), topleft.getY(), bottomright.getX(), bottomright.getY());
File screenshotLocation = new File("Images/"+fileName +".png");
ImageIO.write(imgScreenshot, "png", screenshotLocation);
}
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;
}
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);
}
}
}
}
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);
これは私のバージョンです。C#では、基本的にブルックの回答から大部分を取得し、目的に合わせて変更しました。
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[]));
}
}
@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を使用)
@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
スクロールが必要なときに、クロップのサイズがスクリーンショットのサイズを1ピクセル超えたため、2つが必要でした(少なくともchromeドライバーの場合)。