Selenium Webdriverを使用して、ページ全体ではなく特定の要素のスクリーンショットをキャプチャするにはどうすればよいですか?


82

現在、SeleniumWebDriverを使用してスクリーンショットをキャプチャしようとしています。しかし、私はページ全体のスクリーンショットしか取得できません。ただし、私が望んでいたのは、ページの一部をキャプチャすること、またはIDや特定の要素ロケーターに基づいて特定の要素だけをキャプチャすることです。(たとえば、image id = "Butterfly"で写真をキャプチャしたい)

選択したアイテムまたは要素ごとにスクリーンショットをキャプチャする方法はありますか?


1
AFAIK、機能はページ全体をキャプチャすることだけです。要素IDまたは名前を入力として受け取るスクリーンショット関数はありません。
ヘマンス2012

誰でもc#でBUfferedImageのメソッド呼び出しは何ですか?これに関連する同様の方法は見つかりませんでした。
fj123 2012

回答:


117

以下のようにページ全体のスクリーンショットを切り抜くことで、要素のスクリーンショットを取得できます。

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);

返信ありがとうございます。しかし、なぜ私のウェブドライバーはあなたのものとは違うのですか。IWebDriver、ITakeScreenshotを使用し、OutputType.FILEとBufferedImageはありません...古いバージョンのWebドライバーSeleniumを使用していますか?
fj123 2012

C#Webドライバーバインディングを使用していますか?
スーリヤ2012

はい、そう思います。以前はRCを使用していましたが、最近はWebドライバーを使用するように変更しました。
fj123 2012

この実装はJavaバインディング用です。この概念はC#でも機能するはずです。しかし、私はC#言語についてあまり意識していません。C#と同等のライブラリ(BufferedImage、ImageIO ...)を使用する必要があります
Surya 2012

4
上記のコードはChromeでは機能しません。例外java.awt.image.RasterFormatException:(y + height)がラスターの外側にありますBufferedImage eleScreenshot = fullImg.getSubimage(point.getX()、point.getY()、eleWidth、eleHeight);
リポンアルワシム2016

13

これは、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")

4
element.sizeによって作成されたスクリーンショットdriver.save_screenshotはピクセルの寸法を持っているのに対し、私はそれがポイントで与えられていると確信しています。画面が1以外のピクセル・ツー・ポイントの比率がある場合(例えば、網膜のMacBookには、ポイントごとに2つのピクセルを持っている- 2の比率を)あなたは、乗算に必要whその比で。
BallpointBen

新バージョンでは、@ rovr138の答えを見element.screenshot(「elemenent.png」)を使用することができた
tinyhare

@tinyhare回答が作成されたとき、Firefoxでのみ利用可能でした。今はクロームでも入手できると思います。答えを更新します。
codeslord

1
@puppetメモリ内読み込みの場合はこれを行います。from StringIO import StringIO; from PIL import Image; img = Image.open(StringIO(image))
codeslord

1
@puppetと同様の問題がありました。これが私のために働いたものです: import io; from PIL import Image; img = Image.open(io.BytesIO(image)); img.save("image.png")
SomtoMuotoe19年

9

Node.js、私は動作しますが、それはセレンの公式WebDriverJSに基づいていますが、に基づいていない次のコードを書いたSauceLabs's WebDriverWD.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;
        });
};

EasyImageライブラリが壊れています: "ImageMagickMissingError"
Nizar B.

9

YandexのASHOTフレームワークは、SeleniumWebDriverスクリプトでスクリーンショットを撮るために使用できます。

  • 完全なWebページ
  • ウェブ要素

このフレームワークは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モード、またはそれは、すべての要素をキャプチャしない場合があります。
user1686407 2018

8

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);
    }
}

ありがとうございました。それは非常に役に立ち、要点と完璧でした。
Sorrel Vesper 2016

5

スクリーンショットを撮るのに多くの時間を無駄にしました。あなたのスクリーンショットを保存したいと思います。私はクロム+セレン+ 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); 

1
スクロールせずに表示される要素をキャプチャしようとする限り、これは完全に正常に機能します。要素までスクロールしてキャプチャする必要がある場合、yオフセットはページの上部から計算され、フルスクリーン画像の境界を超えます。したがって、最も簡単な解決策は、画面サイズコードを増やすことですthis.driver.manage()。window()。setSize(new Dimension(1680、1050)); または、cssを介して不要な要素を削除します。適切な解決策は、スクロールからyオフセットを計算することです。
Ichwardort 2015年

3

ディスク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に心ゆくまで入れることができます


3

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の回答が作成されたとき、これは利用できなかった可能性があります。


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();
        }
    }

2

JavaScriptソリューションをお探しの場合は、ここに私の要点があります。

https://gist.github.com/sillicon/4abcd9079a7d29cbb53ebee547b55fba

基本的な考え方は同じです。最初にスクリーンショットを撮り、次にトリミングします。ただし、私のソリューションでは他のライブラリは必要なく、純粋なWebDriverAPIコードのみが必要です。ただし、副作用として、テストブラウザの負荷が増加する可能性があります。


あなたの答えではなく、別のソースへのリンクコードを貼り付けてください
supersan

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"));

1

自動視覚比較用の針ツールhttps://github.com/bfirsh/needleの使用を検討して ください。これには、特定の要素のスクリーンショットを撮ることができる機能が組み込まれています(CSSセレクターによって選択されます)。このツールはSeleniumのWebDriverで動作し、Pythonで記述されています。


1

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);
 }

詳細については、次のリンクを参照してください: [Automation Hub Point](automationhubpoint.blogspot.in/2017/01/…
ER.swatantra 2017

1

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;
}

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);                        
            }
        }
    }
}

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);

私はselenium-java-2.53.1を使用しています、コンパイルグループ: 'org.seleniumhq.selenium'、名前: 'selenium-java'、バージョン: '2.53.1'、chrome-web-driver、私はトリミングしようとしていますウェブページresident.uidai.gov.in/offlineaadhaarの.xpath( ".// img [@class = 'captcha']")ですが、コードが正しく機能していません。ページの間違った部分をトリミングします。キャプチャをトリミングするのを手伝ってくれませんか。
ビジェイ

0

これは私のバージョンです。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[]));
        }
    }

-1

C#を使用していて、私のソリューションにはJavaライブラリが含まれているため、これはうまくいかないと思いますが、他の人が役立つと思うかもしれません。

カスタムスクリーンショットをキャプチャするには、Shutterbugライブラリを使用できます。この目的のための具体的な呼びかけは次のとおりです。

Shutterbug.shootElement(driver, element).save();

-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を使用)


-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スクロールが必要なときに、クロップのサイズがスクリーンショットのサイズを1ピクセル超えたため、2つが必要でした(少なくともchromeドライバーの場合)。


メソッドを試してみると、次のエラーが発生します。「OpenQA.Selenium.Remote.RemoteWebElement」タイプに透過プロキシをキャストできません
shanabus 2017年

私はこれをChromeドライバーでのみ使用していますが、どのドライバーを使用していますか?
thepirat000 2017年

ChromeDriverも使用しています。私のテストではIWebElementsを使用しており、OpenQA.Selenium.SupportnugetパッケージのPageFactoryメソッドに従っています。
shanabus 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.