83

我为此搜索了很多,但找不到解决方案。这是一个类似的问题,在 java 中有一个可能的解决方案。

Python中有类似的解决方案吗?

4

8 回答 8

152

除了 Selenium,此示例还需要 PIL Imaging 库。有时这是作为标准库之一,有时不是,但如果你没有它,你可以安装它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 才能实现的东西,这可能是一个可行的解决方案。

于 2013-04-08T03:16:37.957 回答
41

在 python3.5 中为我工作

from selenium import webdriver


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

ps

保存到文件

image=driver.find_element_by_id('hlogo').screenshot(output_file_path)
于 2017-12-24T10:13:10.777 回答
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()

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

于 2016-06-20T14:17:52.643 回答
6

这是一个可以做到这一点的函数,在传递给裁剪函数之前,必须将大小转换为整数:

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')
于 2017-06-21T21:38:16.160 回答
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()))

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

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)
于 2018-01-28T20:13:56.890 回答
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')
于 2019-11-25T08:47:07.127 回答
2

就这么简单:

element = driver.find_element_by_class_name('myclass')
element.screenshot('screenshot.png')
于 2021-02-27T19:16:19.797 回答
0

我将@randomphobia 的答案转换为一个函数。我还使用了@bummis 的建议,即使用location_once_scrolled_into_view而不是location为了概括页面的大小。

from selenium import webdriver
from PIL import Image
from io import BytesIO

def take_screenshot(element, driver, filename='screenshot.png'):
  location = element.location_once_scrolled_into_view
  size = element.size
  png = driver.get_screenshot_as_png() # saves screenshot of entire page

  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(filename) # saves new cropped image

这是一个要点:https ://gist.github.com/WittmannF/b714d3ceb7b6a5cd50002f11fb5a4929

于 2020-01-10T21:11:30.020 回答