85 votes

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

J'ai beaucoup cherché mais je n'ai pas trouvé de solution. Voici ce qu'il en est une question similaire avec une solution possible en java.

Existe-t-il une solution similaire en Python ?

153voto

RandomPhobia Points 539

Outre Selenium, cet exemple nécessite également la bibliothèque PIL Imaging. Elle est parfois incluse dans les bibliothèques standard, parfois non, mais si vous ne l'avez pas, vous pouvez l'installer à l'aide de la commande 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

et enfin le résultat est... le logo de Stackoverflow !!!

enter image description here

Bien sûr, cela serait excessif pour capturer une image statique, mais si vous voulez capturer quelque chose qui nécessite du Javascript, cela pourrait être une solution viable.

44voto

Iman Kermani Points 397

Cela a fonctionné pour moi avec python3.5

from selenium import webdriver

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

p.s.

Pour enregistrer dans un fichier

image=driver.find_element_by_id('hlogo').screenshot(output_file_path)

7voto

eugene-bright Points 303

J'ai écrit cette fonction utile en 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 d'affichage.
Vous devez installer le module wand pour pouvoir l'utiliser.

6voto

SEDaradji Points 479

Les tailles doivent être converties en nombres entiers avant d'être transmises à la fonction de culture :

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

5voto

StackG Points 83

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 enregistrement préalable 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 "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, et de loin) :

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)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X