2013-02-22 16 views

risposta

76

Questa domanda sembra essere andato a lungo senza una risposta, ma avendo appena lavorato su di esso ho pensato di passare su alcune delle cose che ho imparato

Nota: Oltre selenio questo esempio richiede anche la libreria PIL Imaging. A volte questo è messo in una delle librerie standard e, a volte non lo è, ma se non lo avete potete ottenerlo here

from selenium import webdriver 
from PIL import Image 

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 
fox.save_screenshot('screenshot.png') # saves screenshot of entire page 
fox.quit() 

im = Image.open('screenshot.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, infine, la produzione è .... rullo di tamburi la Stackoverflow logo !!!

enter image description here

ora, naturalmente, questo sarebbe eccessivo per solo afferrare un'immagine statica, ma se il tuo vuole afferrare qualcosa che richiede Javascript per arrivare a questo potrebbe essere una soluzione praticabile.

+14

Puoi anche ottenere lo screenshot direttamente nella memoria: 'img = Image.open (StringIO (base64.decodestring (driver.get_screenshot_as_base64())))' – ejk314

+0

Confermo che questa soluzione (insieme al suggerimento di @ ejk314) funziona molto bene con Selenium 2.38.4, utilizzando il driver di Firefox – cjauvin

+0

Ottima risposta, grazie mille! –

2

Questo tizio chiamato "Cherri" ha fatto un library for Selenium che include questo.

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

Ho scritto questa utile funzione 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() 

Restituisce l'immagine png dell'elemento visualizzato come byte. Limitazione: l'elemento deve essere inserito nella finestra.
È necessario installare il modulo bacchetta per lavorare con esso.

+0

Bel codice! Quando provo con una lunga pagina in chrome, penso che 'x = element.location_once_scrolled_into_view [" x "] y = element.location_once_scrolled_into_view [" y "]' poiché 'location' può restituire una y più grande della finestra. – Vimos

3

Ecco una funzione che fa proprio questo, le dimensioni devono essere colato a interi prima di essere passato alla funzione di ritaglio:

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

Questo è più o meno lo stesso delle risposte accettate, con l'ulteriore errore che non utilizza il selenio, come voleva l'OP. – iled

+0

Utilizza selenio, ma l'istruzione import non è necessaria qui, Include anche la conversione di posizioni da float a int, la funzione img.crop genera un'eccezione se le posizioni non sono numeri interi – SEDaradji

4

Ha lavorato per me in python3.5

from selenium import webdriver 


fox = webdriver.Firefox() 
fox.get('http://stackoverflow.com/') 
element = fox.find_element_by_id('hlogo') 
image = driver.find_element_by_id(html_id_image_captcha).screenshot_as_png 
+0

Funziona perfettamente su Firefox (testato usando 56.0.1), ma non su Chrome (60.0.3112.78). –

2

Espansione sui commenti in risposta alla risposta molto bella di RandomPhobia, ecco due soluzioni con istruzioni di importazione corrette che apriranno uno screenshot a schermo intero senza prima salvare in un file:

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 perché sono sicuro che la prossima domanda è: "Beh questo è grande, ma che uno è più veloce?", Ecco come determinare esso (ho trovato il primo metodo per essere il più veloce da una certa distanza):

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) 
Problemi correlati