web-dev-qa-db-fra.com

Comment prendre une capture d'écran partielle avec Selenium WebDriver en python?

J'ai beaucoup cherché cela, mais je n'ai pas trouvé de solution. Voici ne question similaire avec une solution possible en Java.

Existe-t-il une solution similaire en Python?

62
streamoverflowed

Cette question semble être restée longtemps sans réponse, mais après y avoir travaillé, j'ai pensé que je transmettrais certaines des choses que j'ai apprises

Remarque: Outre Selenium, cet exemple nécessite également la bibliothèque d'imagerie PIL. Parfois, cela est mis dans l'une des bibliothèques standard et parfois ce n'est pas le cas, mais si vous ne l'avez pas, vous pouvez l'obtenir ici

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

et la sortie finale est .... roulement de tambour le logo Stackoverflow !!!

enter image description here

maintenant, bien sûr, ce serait exagéré de simplement saisir une image statique, mais si vous voulez saisir quelque chose qui nécessite Javascript pour y arriver, cela pourrait être une solution viable.

118
RandomPhobia

A travaillé pour moi en 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

J'ai écrit cette fonction utile de 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()

Il renvoie l'image png de l'élément affiché sous forme d'octets. Limitation: l'élément doit tenir dans la fenêtre.
Vous devez installer le module de baguette pour pouvoir l'utiliser.

7
eugene-bright

Voici une fonction qui fait exactement cela, les tailles doivent être converties en entiers avant d'être passées à la fonction de recadrage:

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

En développant les commentaires en réponse à la très belle réponse de RandomPhobia, voici deux solutions avec des déclarations d'importation correctes qui ouvriront une capture d'écran en plein écran sans d'abord enregistrer dans un fichier:

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

Et parce que je suis sûr que votre prochaine question est: "Eh bien, c'est bien mais laquelle est la plus rapide?", Voici comment la déterminer (je trouve que la première méthode est la plus rapide d'une certaine distance):

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

Ce gars nommé "Cherri" a fait un bibliothèque pour Selenium qui inclut cela.

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