我为此进行了很多搜索,但找不到解决方案。 这是java中可能的解决方案的类似问题。
Python中有类似的解决方案吗?
除了硒以外,此示例还需要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才能实现的功能,那可能是一个可行的解决方案。
您也可以直接在内存中获取屏幕截图:img = Image.open(StringIO(base64.decodestring(driver.get_screenshot_as_base64())))
我确认使用Firefox驱动程序,该解决方案(以及@ ejk314s的建议)与Selenium 2.38.4一起使用时效果很好
很好的答案,非常感谢!
内存加载的替代方法是img = fox.get_screenshot_as_png(),然后img = Image.open(StringIO(img))将其加载为PIL映像。
注释来自@ sukrit-gupta的NAA:RandomPhobia,对于不需要滚动的静态页面,您的答案非常有用。万一某人需要从需要滚动的大页面获取图像,则应使用location_once_scrolled_into_view函数。因此,将location = element.location替换为:location = img.location_once_scrolled_into_view另外,请确保使用Chrome而不是Firefox,因为Chrome仅截取可见区域的屏幕快照,而Firefox截取完整标签的屏幕快照。
我们如何捕获浏览器中显示的内容而不滚动页面而不是整个页面。
由于某些原因,im.save(screenshot.png)无法保存。
@User"某种原因还不够"每当您不知道期望什么时,U应该用try / except换行并从Exception打印str(e)。也许您没有正确加载或处理图像,所以保存将不起作用,但是无论如何,使用try块将得到错误并能够解决它。
@yellowcap提出的建议的后续工作:请注意,在Python 3+中,您应该BytesIO而不是StringIO。
图像被放大时,我面临尺寸调整问题。屏幕截图有效,但是裁剪图像似乎无效。有人面对过同样的事情吗?
在MacOS(视网膜)上,由于调整大小/比例,存在像素中的Web元素位置与屏幕快照中的元素位置不匹配的问题
如@Outside_Box所述,有时由于屏幕的像素密度,应进行一些更正。因为element.size以磅为单位,并且crop函数使用像素,所以我们应该使用像素比率来转换大小。 pixel_ratio = fox.execute_script("return window.devicePixelRatio") new_size = old_size * pixel_ratio
屏幕截图的大小和浏览器窗口的大小相同。我必须执行以下操作1.使用driver.get_window_size()获取浏览器窗口的大小2.从浏览器窗口的高度减去地址栏的高度3.现在将屏幕截图的大小调整为设置1和2的新高度和宽度
@vperezb实际上因为old_size是dict而pixel_ratio是int,所以需要重新计算高度和宽度:right = location[x] + old_size[width]* pixel_ratio bottom = location[y] + old_size[height]* pixel_ratio
就像@User提到的那样,im.save不能保存,但是也不会引发错误,对此我应该问一个新的问题吗?当我键入im.show()时,将出现一个所需大小的透明图像窗口
在python3.5中为我工作
from selenium import webdriver
fox = webdriver.Firefox()
fox.get('http://stackoverflow.com/')
image = fox.find_element_by_id('hlogo').screenshot_as_png
@Julius不,不应该-仅当部分屏幕截图与分配了ID的元素完全匹配时才足够。
@Julius仍然不确定它在哪里以及如何工作。在带有Chrome的Python 2.7中,它不起作用。
我使用selenium2在chrome / python 2.7上工作。 image = driver.find_element_by_id(el_id).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图像。
限制:元素必须适合视口。
您必须安装棒模块才能使用它。
好的代码!当我尝试使用chrome中的长页面时,我认为x = element.location_once_scrolled_into_view["x"] y = element.location_once_scrolled_into_view["y"]是因为location可能返回比窗口大的y。
这是一个执行此功能的函数,在将大小传递给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')
这与接受的答案几乎相同,但又增加了一个错误,即OP不希望使用硒。
它确实使用硒,但是这里不需要import语句,它还包括将位置从float转换为int的功能,如果位置不是整数,则img.crop函数将引发异常
TypeError: initial_value must be str or None, not bytes
您的输出是什么(img),是方法还是字节对象?
我不确定我是否理解你的问题
为响应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
无效链接,请对其进行更新。
@PedroLobito实际上是一个被黑的链接。