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

时间:2013-02-22 06:41:47

标签: python selenium

我已经搜索了很多但是找不到解决方案。这是a similar question,在java中有可能的解决方案。

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

9 个答案:

答案 0 :(得分:115)

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

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

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徽标!!!

enter image description here

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

答案 1 :(得分:15)

在python3.5中为我工作

from selenium import webdriver


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

答案 2 :(得分: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模块才能使用它。

答案 3 :(得分:4)

这是一个功能就是这样,大小必须在传递给裁剪函数之前被转换为整数:

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

答案 4 :(得分:3)

扩展评论以回应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)

答案 5 :(得分:2)

这个名叫“Cherri”的家伙制作了library for Selenium,其中包括此内容。

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

答案 6 :(得分:1)

按元素截屏:

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

答案 7 :(得分:1)

就这么简单:

element = driver.find_element_by_class_name('myclass')
element.screenshot('screenshot.png')

答案 8 :(得分: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