ti-enxame.com

Como tirar uma captura de tela parcial com o Selenium WebDriver em python?

Eu procurei muito por isso, mas não consegui encontrar uma solução. Aqui está ma pergunta semelhante com uma possível solução em Java.

Existe uma solução semelhante em Python?

62
streamoverflowed

Esta questão parece ter passado muito tempo sem resposta, mas, tendo acabado de trabalhar, pensei em transmitir algumas das coisas que aprendi.

Nota: Além do Selenium, este exemplo também requer a biblioteca de imagens PIL. Às vezes, isso é colocado como uma das bibliotecas padrão e, às vezes, não, mas se você não o tem, pode obtê-lo aqui

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

e a saída final é .... drum roll o logotipo Stackoverflow !!!

enter image description here

agora é claro que isso seria um exagero apenas por capturar uma imagem estática, mas se você quiser pegar algo que exija Javascript para chegar a isso, pode ser uma solução viável.

118
RandomPhobia

Trabalhou para mim em python3.5

from Selenium import webdriver


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

Eu escrevi esta útil função 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()

Retorna a imagem png do elemento exibido como bytes. Limitação: o elemento deve caber na janela de exibição.
Você deve instalar o módulo de varinha para trabalhar com ele.

7
eugene-bright

Aqui está uma função que faz exatamente isso: Os tamanhos devem ser convertidos em números inteiros antes de serem passados ​​para a função de corte:

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')
4
SEDaradji

Expandindo os comentários em resposta à resposta muito agradável de RandomPhobia, aqui estão duas soluções com instruções de importação corretas que abrirão uma captura de tela em tela cheia sem antes salvar em um arquivo:

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

E porque eu tenho certeza que sua próxima pergunta é: "Bem, isso é ótimo, mas qual é o mais rápido?", Veja como determiná-lo (acho o primeiro método o mais rápido a certa distância):

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)
3
StackG

Esse cara chamado "Cherri" criou um biblioteca para Selenium que inclui isso.

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