[selenium] Selenium Webdriver를 사용하여 전체 페이지가 아닌 특정 요소의 스크린 샷을 캡처하는 방법은 무엇입니까?

현재 Selenium WebDriver를 사용하여 스크린 샷을 캡처하려고합니다. 하지만 전체 페이지 스크린 샷 만 얻을 수 있습니다. 그러나 내가 원했던 것은 페이지의 일부 또는 ID 또는 특정 요소 로케이터를 기반으로 특정 요소를 캡처하는 것입니다. (예를 들어 이미지 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);


답변

다음은 Selenium 웹 드라이버와 Pillow를 사용하는 Python 3 버전입니다. 이 프로그램은 전체 페이지의 스크린 샷을 캡처하고 해당 위치에 따라 요소를 자릅니다. 요소 이미지는 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')

최신 정보

이제 크롬은 개별 요소 스크린 샷도 지원합니다. 따라서 아래와 같이 웹 요소의 스크린 샷을 직접 캡처 할 수 있습니다.

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


답변

에서 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 프레임 워크는 Selenium WebDriver 스크립트에서 스크린 샷을 찍는 데 사용할 수 있습니다.

  • 전체 웹 페이지
  • 웹 요소

이 프레임 워크는 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"));

특정 웹 요소

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

이 기사 에서 자세한 내용과 코드 샘플을 참조하십시오 .


답변

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


답변

Surya의 대답 은 디스크 IO를 포함해도 괜찮다면 훌륭하게 작동합니다. 원하지 않는 경우이 방법이 더 나을 수 있습니다.

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에 마음껏 넣을 수 있습니다.