mirror of
https://gitee.com/g1879/DrissionPage.git
synced 2024-12-10 04:00:23 +08:00
解决同域和异域间跳转问题
This commit is contained in:
parent
5db489c4d9
commit
3c0a4e45cd
@ -233,12 +233,6 @@ class ChromiumBase(BasePage):
|
||||
raise RuntimeError('浏览器已关闭或链接已断开。')
|
||||
return self._tab_obj
|
||||
|
||||
@property
|
||||
def _wait_driver(self):
|
||||
"""返回用于控制浏览器的ChromiumDriver对象,会先等待页面加载完毕"""
|
||||
self.wait.load_complete()
|
||||
return self.driver
|
||||
|
||||
@property
|
||||
def is_loading(self):
|
||||
"""返回页面是否正在加载状态"""
|
||||
@ -341,15 +335,16 @@ class ChromiumBase(BasePage):
|
||||
if ERROR not in r:
|
||||
return r
|
||||
|
||||
if r[ERROR] == 'Cannot find context with specified id':
|
||||
error = r[ERROR]
|
||||
if error == 'Cannot find context with specified id':
|
||||
raise ContextLossError
|
||||
elif r[ERROR] in ('Could not find node with given id', 'Could not find object with given id'):
|
||||
elif error.startswith('Could not find ') and error.endswith(' id'):
|
||||
raise ElementLossError
|
||||
elif r[ERROR] == 'tab closed':
|
||||
elif error == 'tab closed':
|
||||
raise TabClosedError
|
||||
elif r[ERROR] == 'alert exists':
|
||||
elif error == 'alert exists':
|
||||
pass
|
||||
elif r[ERROR] in ('Node does not have a layout object', 'Could not compute box model.'):
|
||||
elif error in ('Node does not have a layout object', 'Could not compute box model.'):
|
||||
raise NoRectError
|
||||
elif r['type'] == 'call_method_error':
|
||||
raise CallMethodError(f'\n错误:{r["error"]}\nmethod:{r["method"]}\nargs:{r["args"]}')
|
||||
@ -468,18 +463,18 @@ class ChromiumBase(BasePage):
|
||||
else:
|
||||
raise ValueError('loc_or_str参数只能是tuple、str、ChromiumElement类型。')
|
||||
|
||||
timeout = timeout if timeout is not None else self.timeout
|
||||
ok = False
|
||||
nodeIds = None
|
||||
search_result = self.run_cdp_loaded('DOM.performSearch', query=loc, includeUserAgentShadowDOM=True)
|
||||
count = search_result['resultCount']
|
||||
|
||||
nodeIds = None
|
||||
timeout = timeout if timeout is not None else self.timeout
|
||||
end_time = perf_counter() + timeout
|
||||
ok = False
|
||||
while True:
|
||||
if count > 0:
|
||||
count = 1 if single else count
|
||||
try:
|
||||
nodeIds = self._wait_driver.DOM.getSearchResults(searchId=search_result['searchId'],
|
||||
nodeIds = self.run_cdp_loaded('DOM.getSearchResults', searchId=search_result['searchId'],
|
||||
fromIndex=0, toIndex=count)
|
||||
if nodeIds['nodeIds'][0] != 0:
|
||||
ok = True
|
||||
|
@ -76,9 +76,6 @@ class ChromiumBase(BasePage):
|
||||
@property
|
||||
def driver(self) -> ChromiumDriver: ...
|
||||
|
||||
@property
|
||||
def _wait_driver(self) -> ChromiumDriver: ...
|
||||
|
||||
@property
|
||||
def is_loading(self) -> bool: ...
|
||||
|
||||
|
@ -11,7 +11,8 @@ from warnings import warn
|
||||
|
||||
from .base import DrissionElement, BaseElement
|
||||
from .common.constants import FRAME_ELEMENT, NoneElement, Settings
|
||||
from .common.errors import ContextLossError, ElementLossError, JavaScriptError, NoRectError, ElementNotFoundError
|
||||
from .common.errors import ContextLossError, ElementLossError, JavaScriptError, NoRectError, ElementNotFoundError, \
|
||||
CallMethodError
|
||||
from .common.keys import keys_to_typing, keyDescriptionForString, keyDefinitions
|
||||
from .common.locator import get_loc
|
||||
from .common.web import make_absolute_link, get_ele_txt, format_html, is_js_func, location_in_viewport, offset_scroll
|
||||
@ -93,8 +94,11 @@ class ChromiumElement(DrissionElement):
|
||||
@property
|
||||
def attrs(self):
|
||||
"""返回元素所有attribute属性"""
|
||||
try:
|
||||
attrs = self.page.run_cdp('DOM.getAttributes', nodeId=self._node_id)['attributes']
|
||||
return {attrs[i]: attrs[i + 1] for i in range(0, len(attrs), 2)}
|
||||
except CallMethodError:
|
||||
return {}
|
||||
|
||||
@property
|
||||
def text(self):
|
||||
|
@ -68,6 +68,10 @@ class ChromiumFrame(ChromiumBase):
|
||||
|
||||
def _reload(self):
|
||||
"""重新获取document"""
|
||||
debug = self._debug
|
||||
if debug:
|
||||
print('reload')
|
||||
|
||||
self._frame_ele = ChromiumElement(self.page, backend_id=self._backend_id)
|
||||
node = self.page.run_cdp('DOM.describeNode', backendNodeId=self._frame_ele.ids.backend_id)['node']
|
||||
|
||||
@ -75,24 +79,34 @@ class ChromiumFrame(ChromiumBase):
|
||||
self._is_diff_domain = False
|
||||
self.doc_ele = ChromiumElement(self.page, backend_id=node['contentDocument']['backendNodeId'])
|
||||
super().__init__(self.address, self.page.tab_id, self.page.timeout)
|
||||
self._debug = debug
|
||||
else:
|
||||
self._is_diff_domain = True
|
||||
self._tab_obj.stop()
|
||||
super().__init__(self.address, self.frame_id, self.page.timeout)
|
||||
obj_id = super().run_js('document;', as_expr=True)['objectId']
|
||||
self.doc_ele = ChromiumElement(self, obj_id=obj_id)
|
||||
self._debug = debug
|
||||
|
||||
def _check_ok(self):
|
||||
"""检查iframe元素是否还能使用,不能使用则重新加载"""
|
||||
"""用于应付同域异域之间跳转导致元素丢失问题"""
|
||||
if self._tab_obj._stopped.is_set():
|
||||
self._reload()
|
||||
|
||||
try:
|
||||
self.page.run_cdp('DOM.describeNode', backendNodeId=self.ids.backend_id)
|
||||
self.page.run_cdp('DOM.describeNode', nodeId=self.ids.node_id)
|
||||
except Exception:
|
||||
self._reload()
|
||||
# sleep(2)
|
||||
|
||||
def _onLoadEventFired(self, **kwargs):
|
||||
"""在页面刷新、变化后重新读取页面内容"""
|
||||
# 用于覆盖父类方法,不能删
|
||||
if self._debug:
|
||||
print('loadEventFired')
|
||||
if self._debug_recorder:
|
||||
self._debug_recorder.add_data((perf_counter(), '加载流程', 'loadEventFired'))
|
||||
|
||||
def _get_new_document(self):
|
||||
"""刷新cdp使用的document数据"""
|
||||
if not self._is_reading:
|
||||
@ -104,8 +118,7 @@ class ChromiumFrame(ChromiumBase):
|
||||
while True:
|
||||
try:
|
||||
if self._is_diff_domain is False:
|
||||
node = self.page.run_cdp('DOM.describeNode',
|
||||
backendNodeId=self.ids.backend_id)['node']
|
||||
node = self.page.run_cdp('DOM.describeNode', backendNodeId=self.ids.backend_id)['node']
|
||||
self.doc_ele = ChromiumElement(self.page, backend_id=node['contentDocument']['backendNodeId'])
|
||||
|
||||
else:
|
||||
@ -414,12 +427,14 @@ class ChromiumFrame(ChromiumBase):
|
||||
:param raise_err: 找不到元素是是否抛出异常,为None时根据全局设置
|
||||
:return: ChromiumElement对象
|
||||
"""
|
||||
self._check_ok()
|
||||
if isinstance(loc_or_ele, ChromiumElement):
|
||||
return loc_or_ele
|
||||
|
||||
self.wait.load_complete()
|
||||
|
||||
return self.doc_ele._ele(loc_or_ele, timeout, raise_err=raise_err) if single else self.doc_ele.eles(loc_or_ele, timeout)
|
||||
return self.doc_ele._ele(loc_or_ele, timeout, raise_err=raise_err) \
|
||||
if single else self.doc_ele.eles(loc_or_ele, timeout)
|
||||
|
||||
def _d_connect(self, to_url, times=0, interval=1, show_errmsg=False, timeout=None):
|
||||
"""尝试连接,重试若干次
|
||||
@ -439,6 +454,7 @@ class ChromiumFrame(ChromiumBase):
|
||||
result = self.driver.Page.navigate(url=to_url, frameId=self.frame_id)
|
||||
|
||||
is_timeout = not self._wait_loaded(timeout)
|
||||
sleep(.5)
|
||||
self.wait.load_complete()
|
||||
|
||||
if is_timeout:
|
||||
|
@ -21,7 +21,7 @@ class ContextLossError(BaseError):
|
||||
|
||||
|
||||
class ElementLossError(BaseError):
|
||||
_info = '页面内无此对象,可能因刷新已失效。'
|
||||
_info = '元素对象因刷新已失效。'
|
||||
|
||||
|
||||
class CallMethodError(BaseError):
|
||||
|
Loading…
x
Reference in New Issue
Block a user