스크린샷

//*스크린샷 찍기
ITakesScreenshot _takesScreenshot = (ITakesScreenshot)_driver;
Screenshot screenshot = _takesScreenshot.GetScreenshot();
screenshot.SaveAsFile("screenshot.png", ScreenshotImageFormat.Png);

저장된 파일을 확인하면 웹 전체스크린샷이 찍혀있습니다.

그런데 만약 특정요소부분만 짤라서 사진을 찍고싶다면??

 


스크린샷 자르기

정확히 로고만 스크린샷을 찍고싶은데 어떻게 해야할까요?

어렵지 않습니다 로고이미지의 요소를 가져온뒤

가로, 세로, 위치 값을 가져와서 그만큼 전체스크린샷에서 잘라 저장하면 됩니다. 

//네이버 로고요소 가져오기
_web_elem = _driver.FindElement(By.XPath("//*[@id='header']/div[1]/div/div[1]/h1/a"));

//스크린샷을 비트맵으로 변경
Bitmap bitmap_screenshot = new Bitmap(new System.IO.MemoryStream(screenshot.AsByteArray));

//*전체스크린샷에서 로고크기에 맞춰자릅니다
Rectangle rect_crop_size = new Rectangle(_web_elem.Location.X, _web_elem.Location.Y, _web_elem.Size.Width, _web_elem.Size.Height);
bitmap_screenshot = bitmap_screenshot.Clone(rect_crop_size, bitmap_screenshot.PixelFormat);
bitmap_screenshot.Save(String.Format(Environment.CurrentDirectory + "//screenshot_2.png", ImageFormat.Png));

//*비트맵은 사용후 꼭 Dispose해야 메모리누수가 발생하지 않습니다
//*Dispose를 사용하지 않으려면 using문으로 사용해도 됩니다
bitmap_screenshot.Dispose();

차근차근 보시면 절대 어렵지 않습니다

 


화면에 보이지 않는 요소 스크린샷

로고는 대부분 사이트 상단에 있어서 웹 접속시 바로 보이기 때문에 스크린샷을 찍을 수 있습니다

그런데 꼭 스크롤을 해야할 정도로 밑에 있는 요소는 스샷을찍고 자르려고하면

System.OutOfMemoryException: '메모리가 부족합니다.'

라고 크래시가 납니다

위에서 우리가 비트맵에 스크린샷바이트값을 입력했고 그 범위를 넘긴것이라고 생각하면됩니다

우리가 직접 웹에서 스크롤을 해도 마찬가지로 크래시가 납니다

 

이유는 아무리 스크롤을해도 스크린샷의 사이즈인 가로,세로길이는 강제로 늘리지 않는 한 모니터사이즈만큼 고정되어 있습니다

그러나 요소의 위치는 스크린샷의 사이즈와 별개로 있기 때문에 단순히 요소의 위치만 구하고 스샷을 자르려고하면 문제가 생기기 마련입니다

전체스크린샷의 사이즈는 1000x1000이라면 스크롤하려는 요소의 위치는 1000,1300으로 스크린샷 사이즈,비트맵사이즈의 범위밖으로 넘어가게되기 때문에 문제가 생깁니다.

 

그래도 해결하는 방법인 다 존재하니 알아봅시다

우선 전체스샷을 찍을때 요소가 보여야겠죠? 이미 이런 기능은 존재합니다!!

개발자모드에서 바로 해당 요소로 스크롤이 됩니다 이걸 우리는 코드에서 작동시켜야하는데 방법은 말이죵

_web_elem = _driver.FindElement(By.XPath("//*[@id='footer']/div/div[3]/div[2]/div[1]/a/img"));
_driver.ExecuteScript("arguments[0].scrollIntoView(true);", _web_elem);

 

딱~ 해보시면 스크롤이 됩니다

이제 안보이던 요소를 스크린샷찍을 수 있게 되었습니다

그 다음 우리는 스크롤된 길이(y축)만큼 추가로 계산을 해야합니다

 

스크린샷은 왼쪽위를 (0,0)으로 기준점을 잡습니다

그런데 스크롤된 웹의 기준점은 (0, 스크롤길이) 입니다

이 격차만큼 우리는 계산을 해줘서 웹 기준점을 0, 0으로 맞춰줘야합니다

 

자 그럴려면 스크롤된 y축값을 가져옵시다

//웹 페이지의 Y기준점 찾기
var y_offset_object =_driver.ExecuteScript("return window.pageYOffset;");
int y_offset = (int)float.Parse(y_offset_object.ToString());

코드가 좀 이상하죠? int로 받고있는데 왜 굳이 float를 거치는지,,,

가끔 특정상황에서는 페이지Y오프셋이 소수점으로 떨어지는 경우가 있습니다.

그래서 바로 int.Parse를 하면 이상하게 작동하더라구요.

안전장치로 일단 float로 불러온뒤 int로 캐스팅후 가져왔습니다

물론 float로 가져와서 바로 사용해도 됩니다만 이따 뺄셈을 해야해서 정확한 계산을 하기 위해 int로 캐스팅해줬습니다

 

y축값을 가져왔으니 우리가 스샷을 찍으려는 요소의 위치를 y축값만큼 뺍니다

//*전체스크린샷에서 요소크기에 맞춰자릅니다
Rectangle rect_crop_size = new Rectangle(
    _web_elem.Location.X,
    _web_elem.Location.Y - y_offset, 
    _web_elem.Size.Width, 
    _web_elem.Size.Height);
bitmap_screenshot = bitmap_screenshot.Clone(rect_crop_size, bitmap_screenshot.PixelFormat);
bitmap_screenshot.Save(String.Format(Environment.CurrentDirectory + "//screenshot_scroll_crop.png", ImageFormat.Png));

y값만 계산했습니다

 

이 방법은 최대스크린샷사이즈보다 큰 요소는 찍기 어렵다는게 단점입니다...

 


분명 Capture node screenshot이라는 편한 기능이 있는데...

개발자모드에서 원하는 요소를 우클릭하면 Capture node screenshot이라는 기능이 있습니다

이걸사용하면 스크롤과 요소사이즈 상관없이 곧바로 요소를 스크린샷할 수 있습니다

하...근데 코드상에서 돌리는 방법은 아무리 삽질해도 안나오네요 아는사람있으면 댓글 부탁드립니다

 

 

https://github.com/ForestBird1/TestSelenium.git

 

GitHub - ForestBird1/TestSelenium

Contribute to ForestBird1/TestSelenium development by creating an account on GitHub.

github.com

 

+ Recent posts