Я много искал для этого, но не смог найти решение. Здесь аналогичный вопрос с возможным решением в java.
Есть ли аналогичное решение в Python?
Я много искал для этого, но не смог найти решение. Здесь аналогичный вопрос с возможным решением в java.
Есть ли аналогичное решение в Python?
Помимо 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 !!!
Теперь, конечно, это было бы излишним просто для захвата статического изображения, но если вы хотите получить что-то, что требует Javascript для этого, может быть жизнеспособным решением.
Работал для меня в python3.5
from selenium import webdriver
fox = webdriver.Firefox()
fox.get('http://stackoverflow.com/')
image = fox.find_element_by_id('hlogo').screenshot_as_png
Я написал эту полезную функцию 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 изображение отображаемого элемента в виде байтов.
Ограничение: элемент должен поместиться в окне просмотра.
Вы должны установить модуль палочки для работы с ним.
Вот функция, которая делает именно это. Размеры должны быть отлиты до целых чисел перед передачей функции 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')
Расширение комментариев в ответ на 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)
Этот парень по имени "Cherri" сделал библиотеку для Selenium, которая включает это.
import SeleniumUrllib as selenium
selenium_urllib = selenium()
selenium_urllib.element_screenshot(selectbyid('elementid'),'path.png')
selenium_urllib.driver ## Access normal webdriver
Не разрешается комментировать, но это больше не работает. Мне нужно было найти другое изображение, чтобы захватить, поскольку образ 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>