Подтвердить что ты не робот

Как сделать частичный скриншот с Selenium WebDriver в python?

Я много искал для этого, но не смог найти решение. Здесь аналогичный вопрос с возможным решением в java.

Есть ли аналогичное решение в Python?

4b9b3361

Ответ 1

Помимо Selenium, этот пример также требует библиотеки изображений PIL. Иногда это помещается как одна из стандартных библиотек, а иногда нет, но если у вас ее нет, вы можете установить ее с помощью pip install Pillow

from selenium import webdriver
from PIL import Image
from io import BytesIO

fox = webdriver.Firefox()
fox.get('http://stackoverflow.com/')

# now that we have the preliminary stuff out of the way time to get that image :D
element = fox.find_element_by_id('hlogo') # find part of the page you want image of
location = element.location
size = element.size
png = fox.get_screenshot_as_png() # saves screenshot of entire page
fox.quit()

im = Image.open(BytesIO(png)) # uses PIL library to open image in memory

left = location['x']
top = location['y']
right = location['x'] + size['width']
bottom = location['y'] + size['height']


im = im.crop((left, top, right, bottom)) # defines crop points
im.save('screenshot.png') # saves new cropped image

и, наконец, вывод... логотип Stackoverflow !!!

enter image description here

Теперь, конечно, это было бы излишним просто для захвата статического изображения, но если вы хотите получить что-то, что требует Javascript для этого, может быть жизнеспособным решением.

Ответ 2

Работал для меня в python3.5

from selenium import webdriver


fox = webdriver.Firefox()
fox.get('http://stackoverflow.com/')
image = fox.find_element_by_id('hlogo').screenshot_as_png

Ответ 3

Я написал эту полезную функцию python3.

from base64 import b64decode
from wand.image import Image
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.common.action_chains import ActionChains
import math

def get_element_screenshot(element: WebElement) -> bytes:
    driver = element._parent
    ActionChains(driver).move_to_element(element).perform()  # focus
    src_base64 = driver.get_screenshot_as_base64()
    scr_png = b64decode(src_base64)
    scr_img = Image(blob=scr_png)

    x = element.location["x"]
    y = element.location["y"]
    w = element.size["width"]
    h = element.size["height"]
    scr_img.crop(
        left=math.floor(x),
        top=math.floor(y),
        width=math.ceil(w),
        height=math.ceil(h),
    )
    return scr_img.make_blob()

Он возвращает png изображение отображаемого элемента в виде байтов. Ограничение: элемент должен поместиться в окне просмотра.
Вы должны установить модуль палочки для работы с ним.

Ответ 4

Вот функция, которая делает именно это. Размеры должны быть отлиты до целых чисел перед передачей функции crop:

from PIL import Image
from StringIO import StringIO
def capture_element(element,driver):
  location = element.location
  size = element.size
  img = driver.get_screenshot_as_png()
  img = Image.open(StringIO(img))
  left = location['x']
  top = location['y']
  right = location['x'] + size['width']
  bottom = location['y'] + size['height']
  img = img.crop((int(left), int(top), int(right), int(bottom)))
  img.save('screenshot.png')

Ответ 5

Расширение комментариев в ответ на RandomPhobia очень приятный ответ: вот два решения с правильными операторами импорта, которые откроют скриншот с полным экраном без первой сохранения в файл:

from selenium import webdriver
from PIL import Image
from StringIO import StringIO
import base64

DRIVER = 'chromedriver'
browser = webdriver.Chrome(DRIVER)

browser.get( "http:\\\\www.bbc.co.uk" )

img 1 = Image.open(StringIO(base64.decodestring(browser.get_screenshot_as_base64())))

img 2 = Image.open(StringIO(browser.get_screenshot_as_png()))

И потому что я уверен, что ваш следующий вопрос: "Что ж, это здорово, но какой из них самый быстрый?", Здесь, как его определить (я нахожу, что первый метод будет самым быстрым на некотором расстоянии):

import timeit

setup = '''
from selenium import webdriver
from PIL import Image
from StringIO import StringIO
import base64

DRIVER = 'chromedriver'
browser = webdriver.Chrome(DRIVER)
browser.get( "http:\\\\www.bbc.co.uk" )

file_name = 'tmp.png'
'''

print timeit.Timer('Image.open(StringIO(browser.get_screenshot_as_png()))', setup=setup).repeat(2, 10)
print timeit.Timer('Image.open(StringIO(base64.decodestring(browser.get_screenshot_as_base64())))', setup=setup).repeat(2, 10)
print timeit.Timer('browser.get_screenshot_as_file(file_name); pil_img = Image.open(file_name)', setup=setup).repeat(2, 10)

Ответ 6

Этот парень по имени "Cherri" сделал библиотеку для Selenium, которая включает это.

import SeleniumUrllib as selenium
selenium_urllib = selenium()
selenium_urllib.element_screenshot(selectbyid('elementid'),'path.png')
selenium_urllib.driver ## Access normal webdriver

Ответ 7

Не разрешается комментировать, но это больше не работает. Мне нужно было найти другое изображение, чтобы захватить, поскольку образ stackoverflow не так, как вы думаете.

from selenium import webdriver
from PIL import Image
from io import BytesIO

fox = webdriver.Firefox()
fox.get("https://www.google.co.uk/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png")

# now that we have the preliminary stuff out of the way time to get that image :D
element = fox.find_element_by_tag_name('img') # find part of the page you want image of
location = element.location
size = element.size
png = fox.get_screenshot_as_png() # saves screenshot of entire page
fox.quit()

im = Image.open(BytesIO(png)) # uses PIL library to open image in memory

left = location['x']
top = location['y']
right = location['x'] + size['width']
bottom = location['y'] + size['height']


im = im.crop((left, top, right, bottom)) # defines crop points
im.save('screenshot.png') # saves new cropped image

Выход ошибки консоли.

Traceback (most recent call last):
  File "image_test2.py", line 15, in <module>
    im = Image.open(BytesIO(png)) # uses PIL library to open image in memory
  File "C:\ProgramData\Anaconda3\lib\site-packages\PIL\Image.py", line 2657, in open
    % (filename if filename else fp))
 OSError: cannot identify image file <_io.BytesIO object at 0x00000283AD0B95C8>