mirror of
https://gitee.com/g1879/DrissionPage.git
synced 2024-12-10 04:00:23 +08:00
支持异域iframe内元素截图,基本完成
This commit is contained in:
parent
6dda0886bc
commit
1550e8d673
@ -631,60 +631,8 @@ class ChromiumBase(BasePage):
|
|||||||
:param right_bottom: 截取范围右下角角坐标
|
:param right_bottom: 截取范围右下角角坐标
|
||||||
:return: 图片完整路径或字节文本
|
:return: 图片完整路径或字节文本
|
||||||
"""
|
"""
|
||||||
if as_bytes:
|
return self._get_screenshot(path=path, as_bytes=as_bytes, as_base64=as_base64,
|
||||||
if as_bytes is True:
|
full_page=full_page, left_top=left_top, right_bottom=right_bottom)
|
||||||
pic_type = 'png'
|
|
||||||
else:
|
|
||||||
if as_bytes not in ('jpg', 'jpeg', 'png', 'webp'):
|
|
||||||
raise ValueError("只能接收 'jpg', 'jpeg', 'png', 'webp' 四种格式。")
|
|
||||||
pic_type = 'jpeg' if as_bytes == 'jpg' else as_bytes
|
|
||||||
|
|
||||||
elif as_base64:
|
|
||||||
if as_base64 is True:
|
|
||||||
pic_type = 'png'
|
|
||||||
else:
|
|
||||||
if as_base64 not in ('jpg', 'jpeg', 'png', 'webp'):
|
|
||||||
raise ValueError("只能接收 'jpg', 'jpeg', 'png', 'webp' 四种格式。")
|
|
||||||
pic_type = 'jpeg' if as_base64 == 'jpg' else as_base64
|
|
||||||
|
|
||||||
else:
|
|
||||||
if not path:
|
|
||||||
path = f'{self.title}.jpg'
|
|
||||||
path = get_usable_path(path)
|
|
||||||
pic_type = path.suffix.lower()
|
|
||||||
if pic_type not in ('.jpg', '.jpeg', '.png', '.webp'):
|
|
||||||
raise TypeError(f'不支持的文件格式:{pic_type}。')
|
|
||||||
pic_type = 'jpeg' if pic_type == '.jpg' else pic_type[1:]
|
|
||||||
|
|
||||||
width, height = self.size
|
|
||||||
if full_page:
|
|
||||||
vp = {'x': 0, 'y': 0, 'width': width, 'height': height, 'scale': 1}
|
|
||||||
png = self.run_cdp_loaded('Page.captureScreenshot', format=pic_type,
|
|
||||||
captureBeyondViewport=True, clip=vp)['data']
|
|
||||||
else:
|
|
||||||
if left_top and right_bottom:
|
|
||||||
x, y = left_top
|
|
||||||
w = right_bottom[0] - x
|
|
||||||
h = right_bottom[1] - y
|
|
||||||
vp = {'x': x, 'y': y, 'width': w, 'height': h, 'scale': 1}
|
|
||||||
png = self.run_cdp_loaded('Page.captureScreenshot', format=pic_type,
|
|
||||||
captureBeyondViewport=False, clip=vp)['data']
|
|
||||||
else:
|
|
||||||
png = self.run_cdp_loaded('Page.captureScreenshot', format=pic_type)['data']
|
|
||||||
|
|
||||||
if as_base64:
|
|
||||||
return png
|
|
||||||
|
|
||||||
from base64 import b64decode
|
|
||||||
png = b64decode(png)
|
|
||||||
|
|
||||||
if as_bytes:
|
|
||||||
return png
|
|
||||||
|
|
||||||
path.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
with open(path, 'wb') as f:
|
|
||||||
f.write(png)
|
|
||||||
return str(path.absolute())
|
|
||||||
|
|
||||||
def clear_cache(self, session_storage=True, local_storage=True, cache=True, cookies=True):
|
def clear_cache(self, session_storage=True, local_storage=True, cache=True, cookies=True):
|
||||||
"""清除缓存,可选要清除的项
|
"""清除缓存,可选要清除的项
|
||||||
@ -749,6 +697,73 @@ class ChromiumBase(BasePage):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def _get_screenshot(self, path=None, as_bytes=None, as_base64=None,
|
||||||
|
full_page=False, left_top=None, right_bottom=None, ele=None):
|
||||||
|
"""对页面进行截图,可对整个网页、可见网页、指定范围截图。对可视范围外截图需要90以上版本浏览器支持
|
||||||
|
:param path: 完整路径,后缀可选 'jpg','jpeg','png','webp'
|
||||||
|
:param as_bytes: 是否以字节形式返回图片,可选 'jpg','jpeg','png','webp',生效时path参数和as_base64参数无效
|
||||||
|
:param as_base64: 是否以base64字符串形式返回图片,可选 'jpg','jpeg','png','webp',生效时path参数无效
|
||||||
|
:param full_page: 是否整页截图,为True截取整个网页,为False截取可视窗口
|
||||||
|
:param left_top: 截取范围左上角坐标
|
||||||
|
:param right_bottom: 截取范围右下角角坐标
|
||||||
|
:param ele: 为异域iframe内元素截图设置
|
||||||
|
:return: 图片完整路径或字节文本
|
||||||
|
"""
|
||||||
|
if as_bytes:
|
||||||
|
if as_bytes is True:
|
||||||
|
pic_type = 'png'
|
||||||
|
else:
|
||||||
|
if as_bytes not in ('jpg', 'jpeg', 'png', 'webp'):
|
||||||
|
raise ValueError("只能接收 'jpg', 'jpeg', 'png', 'webp' 四种格式。")
|
||||||
|
pic_type = 'jpeg' if as_bytes == 'jpg' else as_bytes
|
||||||
|
|
||||||
|
elif as_base64:
|
||||||
|
if as_base64 is True:
|
||||||
|
pic_type = 'png'
|
||||||
|
else:
|
||||||
|
if as_base64 not in ('jpg', 'jpeg', 'png', 'webp'):
|
||||||
|
raise ValueError("只能接收 'jpg', 'jpeg', 'png', 'webp' 四种格式。")
|
||||||
|
pic_type = 'jpeg' if as_base64 == 'jpg' else as_base64
|
||||||
|
|
||||||
|
else:
|
||||||
|
if not path:
|
||||||
|
path = f'{self.title}.jpg'
|
||||||
|
path = get_usable_path(path)
|
||||||
|
pic_type = path.suffix.lower()
|
||||||
|
if pic_type not in ('.jpg', '.jpeg', '.png', '.webp'):
|
||||||
|
raise TypeError(f'不支持的文件格式:{pic_type}。')
|
||||||
|
pic_type = 'jpeg' if pic_type == '.jpg' else pic_type[1:]
|
||||||
|
|
||||||
|
width, height = self.size
|
||||||
|
if full_page:
|
||||||
|
vp = {'x': 0, 'y': 0, 'width': width, 'height': height, 'scale': 1}
|
||||||
|
png = self.run_cdp_loaded('Page.captureScreenshot', format=pic_type,
|
||||||
|
captureBeyondViewport=True, clip=vp)['data']
|
||||||
|
else:
|
||||||
|
if left_top and right_bottom:
|
||||||
|
x, y = left_top
|
||||||
|
w = right_bottom[0] - x
|
||||||
|
h = right_bottom[1] - y
|
||||||
|
vp = {'x': x, 'y': y, 'width': w, 'height': h, 'scale': 1}
|
||||||
|
png = self.run_cdp_loaded('Page.captureScreenshot', format=pic_type,
|
||||||
|
captureBeyondViewport=False, clip=vp)['data']
|
||||||
|
else:
|
||||||
|
png = self.run_cdp_loaded('Page.captureScreenshot', format=pic_type)['data']
|
||||||
|
|
||||||
|
if as_base64:
|
||||||
|
return png
|
||||||
|
|
||||||
|
from base64 import b64decode
|
||||||
|
png = b64decode(png)
|
||||||
|
|
||||||
|
if as_bytes:
|
||||||
|
return png
|
||||||
|
|
||||||
|
path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
with open(path, 'wb') as f:
|
||||||
|
f.write(png)
|
||||||
|
return str(path.absolute())
|
||||||
|
|
||||||
# ------------------准备废弃----------------------
|
# ------------------准备废弃----------------------
|
||||||
def wait_loading(self, timeout=None):
|
def wait_loading(self, timeout=None):
|
||||||
"""阻塞程序,等待页面进入加载状态
|
"""阻塞程序,等待页面进入加载状态
|
||||||
|
@ -183,6 +183,13 @@ class ChromiumBase(BasePage):
|
|||||||
left_top: Tuple[int, int] = None,
|
left_top: Tuple[int, int] = None,
|
||||||
right_bottom: Tuple[int, int] = None) -> Union[str, bytes]: ...
|
right_bottom: Tuple[int, int] = None) -> Union[str, bytes]: ...
|
||||||
|
|
||||||
|
def _get_screenshot(self, path: [str, Path] = None,
|
||||||
|
as_bytes: [bool, str] = None, as_base64: [bool, str] = None,
|
||||||
|
full_page: bool = False,
|
||||||
|
left_top: Tuple[int, int] = None,
|
||||||
|
right_bottom: Tuple[int, int] = None,
|
||||||
|
ele: ChromiumElement = None) -> Union[str, bytes]: ...
|
||||||
|
|
||||||
def clear_cache(self,
|
def clear_cache(self,
|
||||||
session_storage: bool = True,
|
session_storage: bool = True,
|
||||||
local_storage: bool = True,
|
local_storage: bool = True,
|
||||||
|
@ -485,8 +485,8 @@ class ChromiumElement(DrissionElement):
|
|||||||
right_bottom = (left + width, top + height)
|
right_bottom = (left + width, top + height)
|
||||||
if not path:
|
if not path:
|
||||||
path = f'{self.tag}.jpg'
|
path = f'{self.tag}.jpg'
|
||||||
return self.page.get_screenshot(path, as_bytes=as_bytes, as_base64=as_base64, full_page=False,
|
return self.page._get_screenshot(path, as_bytes=as_bytes, as_base64=as_base64, full_page=False,
|
||||||
left_top=left_top, right_bottom=right_bottom)
|
left_top=left_top, right_bottom=right_bottom, ele=self)
|
||||||
|
|
||||||
def input(self, vals, clear=True):
|
def input(self, vals, clear=True):
|
||||||
"""输入文本或组合键,也可用于输入文件路径到input元素(路径间用\n间隔)
|
"""输入文本或组合键,也可用于输入文件路径到input元素(路径间用\n间隔)
|
||||||
|
@ -7,6 +7,7 @@ from re import search
|
|||||||
from time import sleep, perf_counter
|
from time import sleep, perf_counter
|
||||||
from warnings import warn
|
from warnings import warn
|
||||||
|
|
||||||
|
from .commons.tools import get_usable_path
|
||||||
from .chromium_base import ChromiumBase, ChromiumPageScroll, ChromiumBaseSetter
|
from .chromium_base import ChromiumBase, ChromiumPageScroll, ChromiumBaseSetter
|
||||||
from .chromium_element import ChromiumElement
|
from .chromium_element import ChromiumElement
|
||||||
|
|
||||||
@ -402,23 +403,73 @@ class ChromiumFrame(ChromiumBase):
|
|||||||
self._check_ok()
|
self._check_ok()
|
||||||
return self.frame_ele.afters(filter_loc, timeout)
|
return self.frame_ele.afters(filter_loc, timeout)
|
||||||
|
|
||||||
def get_screenshot(self, path=None, as_bytes=None, as_base64=None,
|
def get_screenshot(self, path=None, as_bytes=None, as_base64=None):
|
||||||
full_page=False, left_top=None, right_bottom=None):
|
|
||||||
"""对页面进行截图,可对整个网页、可见网页、指定范围截图。对可视范围外截图需要90以上版本浏览器支持
|
"""对页面进行截图,可对整个网页、可见网页、指定范围截图。对可视范围外截图需要90以上版本浏览器支持
|
||||||
:param path: 完整路径,后缀可选 'jpg','jpeg','png','webp'
|
:param path: 完整路径,后缀可选 'jpg','jpeg','png','webp'
|
||||||
:param as_bytes: 是否以字节形式返回图片,可选 'jpg','jpeg','png','webp',生效时path参数和as_base64参数无效
|
:param as_bytes: 是否以字节形式返回图片,可选 'jpg','jpeg','png','webp',生效时path参数和as_base64参数无效
|
||||||
:param as_base64: 是否以base64字符串形式返回图片,可选 'jpg','jpeg','png','webp',生效时path参数无效
|
:param as_base64: 是否以base64字符串形式返回图片,可选 'jpg','jpeg','png','webp',生效时path参数无效
|
||||||
|
:return: 图片完整路径或字节文本
|
||||||
|
"""
|
||||||
|
return self.frame_ele.get_screenshot(path=path, as_bytes=as_bytes, as_base64=as_base64)
|
||||||
|
|
||||||
|
def _get_screenshot(self, path=None, as_bytes: [bool, str] = None, as_base64: [bool, str] = None,
|
||||||
|
full_page=False, left_top=None, right_bottom=None, ele=None):
|
||||||
|
"""实现对元素截图
|
||||||
|
:param path: 完整路径,后缀可选 'jpg','jpeg','png','webp'
|
||||||
|
:param as_bytes: 是否以字节形式返回图片,可选 'jpg','jpeg','png','webp',生效时path参数和as_base64参数无效
|
||||||
|
:param as_base64: 是否以base64字符串形式返回图片,可选 'jpg','jpeg','png','webp',生效时path参数无效
|
||||||
:param full_page: 是否整页截图,为True截取整个网页,为False截取可视窗口
|
:param full_page: 是否整页截图,为True截取整个网页,为False截取可视窗口
|
||||||
:param left_top: 截取范围左上角坐标
|
:param left_top: 截取范围左上角坐标
|
||||||
:param right_bottom: 截取范围右下角角坐标
|
:param right_bottom: 截取范围右下角角坐标
|
||||||
|
:param ele: 为异域iframe内元素截图设置
|
||||||
:return: 图片完整路径或字节文本
|
:return: 图片完整路径或字节文本
|
||||||
"""
|
"""
|
||||||
if full_page:
|
if not self._is_diff_domain:
|
||||||
raise RuntimeError('暂未实现对iframe全页截图功能。')
|
return super().get_screenshot(path=path, as_bytes=as_bytes, as_base64=as_base64,
|
||||||
if left_top is None and right_bottom is None:
|
full_page=full_page, left_top=left_top, right_bottom=right_bottom)
|
||||||
return self.frame_ele.get_screenshot(path=path, as_bytes=as_bytes, as_base64=as_base64)
|
|
||||||
else:
|
else:
|
||||||
raise RuntimeError('暂未实现对异域iframe内元素截图功能。')
|
if as_bytes:
|
||||||
|
if as_bytes is True:
|
||||||
|
pic_type = 'png'
|
||||||
|
else:
|
||||||
|
if as_bytes not in ('jpg', 'jpeg', 'png', 'webp'):
|
||||||
|
raise ValueError("只能接收 'jpg', 'jpeg', 'png', 'webp' 四种格式。")
|
||||||
|
pic_type = 'jpeg' if as_bytes == 'jpg' else as_bytes
|
||||||
|
|
||||||
|
elif as_base64:
|
||||||
|
if as_base64 is True:
|
||||||
|
pic_type = 'png'
|
||||||
|
else:
|
||||||
|
if as_base64 not in ('jpg', 'jpeg', 'png', 'webp'):
|
||||||
|
raise ValueError("只能接收 'jpg', 'jpeg', 'png', 'webp' 四种格式。")
|
||||||
|
pic_type = 'jpeg' if as_base64 == 'jpg' else as_base64
|
||||||
|
|
||||||
|
else:
|
||||||
|
if not path:
|
||||||
|
path = f'{self.title}.jpg'
|
||||||
|
path = get_usable_path(path)
|
||||||
|
pic_type = path.suffix.lower()
|
||||||
|
if pic_type not in ('.jpg', '.jpeg', '.png', '.webp'):
|
||||||
|
raise TypeError(f'不支持的文件格式:{pic_type}。')
|
||||||
|
pic_type = 'jpeg' if pic_type == '.jpg' else pic_type[1:]
|
||||||
|
|
||||||
|
self.scroll.to_see(ele)
|
||||||
|
cx, cy = ele.locations.viewport_location
|
||||||
|
w, h = ele.size
|
||||||
|
img_data = f'data:image/{pic_type};base64,{self.frame_ele.get_screenshot(as_base64=True)}'
|
||||||
|
body = self.page('t:body')
|
||||||
|
first_child = body('c::first-child')
|
||||||
|
js = f'''
|
||||||
|
haskell = document.createElement('img');
|
||||||
|
haskell.src = "{img_data}";
|
||||||
|
arguments[0].insertBefore(haskell, this);
|
||||||
|
return haskell;'''
|
||||||
|
new_ele = first_child.run_js(js, body)
|
||||||
|
r = self.page.get_screenshot(path=path, as_bytes=as_bytes, as_base64=as_base64,
|
||||||
|
left_top=(cx, cy), right_bottom=(cx + w, cy + h))
|
||||||
|
self.page.remove_ele(new_ele)
|
||||||
|
return r
|
||||||
|
|
||||||
def _find_elements(self, loc_or_ele, timeout=None, single=True, relative=False, raise_err=None):
|
def _find_elements(self, loc_or_ele, timeout=None, single=True, relative=False, raise_err=None):
|
||||||
"""在frame内查找单个元素
|
"""在frame内查找单个元素
|
||||||
|
@ -152,10 +152,15 @@ class ChromiumFrame(ChromiumBase):
|
|||||||
timeout: float = ...) -> List[Union[ChromiumElement, ChromiumFrame, str]]: ...
|
timeout: float = ...) -> List[Union[ChromiumElement, ChromiumFrame, str]]: ...
|
||||||
|
|
||||||
def get_screenshot(self, path: [str, Path] = None,
|
def get_screenshot(self, path: [str, Path] = None,
|
||||||
as_bytes: [bool, str] = None, as_base64: [bool, str] = None,
|
as_bytes: [bool, str] = None,
|
||||||
full_page: bool = False,
|
as_base64: [bool, str] = None) -> Union[str, bytes]: ...
|
||||||
left_top: Tuple[int, int] = None,
|
|
||||||
right_bottom: Tuple[int, int] = None) -> Union[str, bytes]: ...
|
def _get_screenshot(self, path: [str, Path] = None,
|
||||||
|
as_bytes: [bool, str] = None, as_base64: [bool, str] = None,
|
||||||
|
full_page: bool = False,
|
||||||
|
left_top: Tuple[int, int] = None,
|
||||||
|
right_bottom: Tuple[int, int] = None,
|
||||||
|
ele: ChromiumElement = None) -> Union[str, bytes]: ...
|
||||||
|
|
||||||
def _find_elements(self, loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, ChromiumFrame],
|
def _find_elements(self, loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, ChromiumFrame],
|
||||||
timeout: float = None, single: bool = True, relative: bool = False, raise_err: bool = None) \
|
timeout: float = None, single: bool = True, relative: bool = False, raise_err: bool = None) \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user