如何在 python 中使用 Selenium WebDriver 截取部分屏幕截图?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15018372/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to take partial screenshot with Selenium WebDriver in python?
提问by streamoverflowed
I have searched a lot for this but couldn't find a solution. Here's a similar questionwith a possible solution in java.
我为此搜索了很多,但找不到解决方案。这是一个类似的问题,在 Java 中有一个可能的解决方案。
Is there a similar solution in Python?
Python中是否有类似的解决方案?
采纳答案by RandomPhobia
Other than Selenium, this example also requires the PIL Imaging library. Sometimes this is put in as one of the standard libraries and sometimes it's not, but if you don't have it you can install it with pip install Pillow
除了 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
and finally the output is... the Stackoverflow logo!!!
最后输出是…… Stackoverflow 标志!!!


Now of course this would be overkill for just grabbing a static image but if your want to grab something that requires Javascript to get to this could be a viable solution.
当然,这对于仅抓取静态图像来说是多余的,但是如果您想抓取需要 Javascript 才能到达的东西,这可能是一个可行的解决方案。
回答by eugene-bright
I wrote this useful python3 function.
我写了这个有用的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()
It returns png image of displayed element as bytes.
Limitation: element must fit in viewport.
You must install wand module to work with it.
它以字节形式返回显示元素的 png 图像。限制:元素必须适合视口。
您必须安装魔杖模块才能使用它。
回答by SEDaradji
Here is a function that does just that, The sizes must be casted to integers before being passed to the crop function :
这是一个执行此操作的函数,在传递给裁剪函数之前,必须将大小转换为整数:
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')
回答by Iman Kermani
Worked for me in python3.5
在 python3.5 中为我工作
from selenium import webdriver
fox = webdriver.Firefox()
fox.get('http://stackoverflow.com/')
image = fox.find_element_by_id('hlogo').screenshot_as_png
回答by StackG
Expanding on the comments in response to RandomPhobia's very nice answer, here are two solutions with correct import statements that will open a full-screen screenshot without first saving to a file:
扩展评论以响应 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()))
And because I'm sure your next question is, "Well that's great but which one is fastest?", here's how to determine it (I find the first method to be the fastest by some distance):
因为我确定你的下一个问题是,“这很好,但哪个最快?”,这里是如何确定它(我发现第一种方法在一定距离内是最快的):
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)
回答by Gavriel Cohen
Screenshot by Element:
元素截图:
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')
回答by Fernando Wittmann
I converted @randomphobia's answer into a function. I also used @bummis' suggestion of using location_once_scrolled_into_viewinstead of locationin order to generalize no matter the size of the page.
我将@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
Here's a gist: https://gist.github.com/WittmannF/b714d3ceb7b6a5cd50002f11fb5a4929
这是一个要点:https: //gist.github.com/WittmannF/b714d3ceb7b6a5cd50002f11fb5a4929

