如何在python中使用Selenium WebDriver进行部分截图?

str*_*wed 68 python selenium

我已经搜索了很多但是找不到解决方案.这是一个与 java中可能的解决方案类似的问题.

Python中是否有类似的解决方案?

Ran*_*bia 123

这个问题似乎已经花了很长时间没有答案,但刚刚开始研究我认为我会传授一些我学到的东西

注意:除了Selenium之外,此示例还需要PIL Imaging库.有时这是作为标准库之一,有时它不是,但如果你没有它,你可以在这里得到它

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
Run Code Online (Sandbox Code Playgroud)

最后的输出是...... 滚动 Stackoverflow标志!!!

在此输入图像描述

现在当然这对于仅仅抓取静态图像来说是过度的,但是如果你想抓住需要Javascript来实现这一点的东西可能是一个可行的解决方案.

  • 您还可以直接在内存中获取屏幕截图:`img = Image.open(StringIO(base64.decodestring(driver.get_screenshot_as_base64())))` (17认同)
  • 内存加载的替代方法是`img = fox.get_screenshot_as_png()`然后`img = Image.open(StringIO(img))`将其加载为PIL图像. (7认同)
  • 关注@yellowcap的建议:注意Python 3+,你应该`BytesIO`而不是`StringIO`. (6认同)
  • 来自@ sukrit-gupta的NAA的评论:*RandomPhobia,对于不需要滚动的静态页面,你的答案很有用.如果有人需要从需要滚动的大页面获取图像,则应使用location_once_scrolled_into_view函数.因此,使用:location = img.location_once_scrolled_into_view替换,location = element.location此外,请确保使用Chrome而不是Firefox,因为Chrome仅截取可见区域的屏幕截图,而Firefox则截取完整标签的屏幕截图.* (5认同)
  • 图像被放大时,我面临调整大小的问题。屏幕截图有效,但裁剪图像似乎无效。有人面对过同样的事情吗? (4认同)
  • 如@Outside_Box所述,有时由于屏幕的像素密度,应进行一些更正。因为** element.size以磅为单位**,并且crop函数使用像素**,所以我们应该使用像素比率来转换尺寸。pixel_ratio = fox.execute_script(“ return window.devicePixelRatio”)`new_size = old_size * pixel_ratio` (3认同)

Ima*_*ani 24

在python3.5中为我工作

from selenium import webdriver


fox = webdriver.Firefox()
fox.get('http://stackoverflow.com/')
image = fox.find_element_by_id('hlogo').screenshot_as_png
Run Code Online (Sandbox Code Playgroud)

  • @tanvi @Lakshmi 你们可以做`image = driver.find_element_by_id('el_id').screenshot(output_file_path)`。请参阅[此处](https://selenium-python.readthedocs.io/api.html#selenium.webdriver.remote.webelement.WebElement.screenshot)获取API文档。 (2认同)

eug*_*ght 7

我写了这个有用的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()
Run Code Online (Sandbox Code Playgroud)

它返回显示元素的png图像作为字节.限制:元素必须适合视口.
您必须安装wand模块才能使用它.


SED*_*dji 6

这是一个执行此功能的函数,在将大小传递给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')
Run Code Online (Sandbox Code Playgroud)


Sta*_*ckG 5

扩展评论以响应 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()))
Run Code Online (Sandbox Code Playgroud)

因为我确定你的下一个问题是,“这很好,但哪个最快?”,这里是如何确定它(我发现第一种方法在一定距离内是最快的):

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)
Run Code Online (Sandbox Code Playgroud)


Gav*_*hen 5

元素截图:

from PIL import Image
from io import BytesIO


image = self.browser.driver.find_element_by_class_name('example.bla.bla').screenshot_as_png
im = Image.open(BytesIO(image))  # uses PIL library to open image in memory
im.save('example.png')
Run Code Online (Sandbox Code Playgroud)