增加匹配开头和结尾语法;页面对象增加窗口状态属性;设置平滑滚动时自动切换是否等待;ChromiumPage设置cookies时自动添加域名

This commit is contained in:
g1879 2023-03-07 15:36:13 +08:00
parent 04e82ee5e6
commit ac52c699a5
6 changed files with 69 additions and 18 deletions

View File

@ -8,6 +8,7 @@ from json import loads, JSONDecodeError
from os import sep
from pathlib import Path
from time import perf_counter, sleep, time
from urllib.parse import urlparse
from warnings import warn
from requests import Session
@ -990,11 +991,10 @@ class ChromiumBaseSetter(object):
result_cookies = []
for cookie in cookies:
if not cookie.get('domain', None):
continue
c = {'value': '' if cookie['value'] is None else cookie['value'],
'name': cookie['name'],
'domain': cookie['domain']}
result_cookies.append(c)
cookie['domain'] = urlparse(self._page.url).netloc
result_cookies.append({'value': '' if cookie['value'] is None else cookie['value'],
'name': cookie['name'],
'domain': cookie['domain']})
self._page.run_cdp_loaded('Network.setCookies', cookies=result_cookies)
def upload_files(self, files):
@ -1192,3 +1192,4 @@ class PageScrollSetter(object):
raise TypeError('on_off必须为bool。')
b = 'smooth' if on_off else 'auto'
self._scroll._driver.run_js(f'document.documentElement.style.setProperty("scroll-behavior","{b}");')
self._scroll._wait_complete = on_off

View File

@ -402,6 +402,11 @@ class ChromiumTabRect(object):
def __init__(self, page):
self._page = page
@property
def window_state(self):
"""返回窗口状态normal、fullscreen、maximized、 minimized"""
return self._get_browser_rect()['windowState']
@property
def browser_location(self):
"""返回浏览器在屏幕上的坐标,左上角为(0, 0)"""

View File

@ -116,6 +116,9 @@ class ChromiumTabRect(object):
def __init__(self, page: ChromiumPage):
self._page: ChromiumPage = ...
@property
def window_state(self) -> str: ...
@property
def browser_location(self) -> Tuple[int, int]: ...

View File

@ -99,7 +99,7 @@ def set_prefs(opt):
prefs = opt.preferences
del_list = opt._prefs_to_del
else:
prefs = opt.experimental_options.get('prefs', None)
prefs = opt.experimental_options.get('prefs', [])
del_list = []
if not opt.user_data_path:

View File

@ -36,19 +36,19 @@ def get_loc(loc, translate_css=False):
def str_to_loc(loc):
"""处理元素查找语句
查找方式属性tag name及属性文本xpathcss selectoridclass
@表示属性.表示class#表示id=表示精确匹配,:表示模糊匹配,无控制字符串时默认搜索该字符串
:param loc: 查找语法字符串
:return: 匹配符元组
"""
loc_by = 'xpath'
if loc.startswith('.'):
if loc.startswith(('.=', '.:',)):
if loc.startswith(('.=', '.:', '.^', '.$')):
loc = loc.replace('.', '@class', 1)
else:
loc = loc.replace('.', '@class=', 1)
elif loc.startswith('#'):
if loc.startswith(('#=', '#:',)):
if loc.startswith(('#=', '#:', '#^', '#$')):
loc = loc.replace('#', '@id', 1)
else:
loc = loc.replace('#', '@id=', 1)
@ -56,7 +56,7 @@ def str_to_loc(loc):
elif loc.startswith(('t:', 't=')):
loc = f'tag:{loc[2:]}'
elif loc.startswith(('tx:', 'tx=')):
elif loc.startswith(('tx:', 'tx=', 'tx^', 'tx$')):
loc = f'text{loc[2:]}'
# ------------------------------------------------------------------
@ -87,9 +87,17 @@ def str_to_loc(loc):
# 根据文本查找
elif loc.startswith('text='):
loc_str = f'//*[text()={_make_search_str(loc[5:])}]'
elif loc.startswith('text:') and loc != 'text:':
loc_str = f'//*/text()[contains(., {_make_search_str(loc[5:])})]/..'
elif loc.startswith('text^') and loc != 'text^':
loc_str = f'//*/text()[starts-with(., {_make_search_str(loc[5:])})]/..'
elif loc.startswith('text$') and loc != 'text$':
loc_str = f'//*/text()[substring(., string-length(.) - string-length({_make_search_str(loc[5:])}) +1) = ' \
f'{_make_search_str(loc[5:])}]/..'
# 用xpath查找
elif loc.startswith(('xpath:', 'xpath=')) and loc not in ('xpath:', 'xpath='):
loc_str = loc[6:]
@ -100,7 +108,7 @@ def str_to_loc(loc):
elif loc.startswith(('css:', 'css=')) and loc not in ('css:', 'css='):
loc_by = 'css selector'
loc_str = loc[4:]
elif loc.startswith(('c:', 'c=')) and loc not in ('c:', 'c='):
elif loc.startswith(('c:', 'cx=')) and loc not in ('c:', 'cx='):
loc_by = 'css selector'
loc_str = loc[2:]
@ -126,24 +134,44 @@ def _make_single_xpath_str(tag: str, text: str) -> str:
arg_str = 'not(@*)'
else:
r = split(r'([:=])', text, maxsplit=1)
r = split(r'([:=$^])', text, maxsplit=1)
len_r = len(r)
len_r0 = len(r[0])
if len_r != 3 and len_r0 > 1:
arg_str = 'normalize-space(text())' if r[0] in ('@text()', '@tx()') else f'{r[0]}'
elif len_r == 3 and len_r0 > 1:
if r[1] == '=': # 精确查找
symbol = r[1]
if symbol == '=': # 精确查找
arg = '.' if r[0] in ('@text()', '@tx()') else r[0]
arg_str = f'{arg}={_make_search_str(r[2])}'
else: # 模糊查找
elif symbol == '^': # 开头开头
if r[0] in ('@text()', '@tx()'):
txt_str = f'/text()[starts-with(., {_make_search_str(r[2])})]/..'
arg_str = ''
else:
arg_str = f"starts-with({r[0]},{_make_search_str(r[2])})"
elif symbol == '$': # 匹配结尾
if r[0] in ('@text()', '@tx()'):
txt_str = f'/text()[substring(., string-length(.) - string-length({_make_search_str(r[2])}) +1) ' \
f'= {_make_search_str(r[2])}]/..'
arg_str = ''
else:
arg_str = f'substring({r[0]}, string-length({r[0]}) - string-length({_make_search_str(r[2])}) +1)' \
f' = {_make_search_str(r[2])}'
elif symbol == ':': # 模糊查找
if r[0] in ('@text()', '@tx()'):
txt_str = f'/text()[contains(., {_make_search_str(r[2])})]/..'
arg_str = ''
else:
arg_str = f"contains({r[0]},{_make_search_str(r[2])})"
else:
raise ValueError(f'符号不正确:{symbol}')
if arg_str:
arg_list.append(arg_str)
arg_str = ' and '.join(arg_list)
@ -161,7 +189,7 @@ def _make_multi_xpath_str(tag: str, text: str, _and: bool = True) -> str:
args = text.split('@@') if _and else text.split('@|')
for arg in args[1:]:
r = split(r'([:=])', arg, maxsplit=1)
r = split(r'([:=$^])', arg, maxsplit=1)
arg_str = ''
len_r = len(r)
@ -176,11 +204,23 @@ def _make_multi_xpath_str(tag: str, text: str, _and: bool = True) -> str:
elif len_r == 3: # 属性名和内容都有
arg = '.' if r[0] in ('text()', 'tx()') else f'@{r[0]}'
if r[1] == '=':
symbol = r[1]
if symbol == '=':
arg_str = f'{arg}={_make_search_str(r[2])}'
else:
elif symbol == ':':
arg_str = f'contains({arg},{_make_search_str(r[2])})'
elif symbol == '^':
arg_str = f'starts-with({arg},{_make_search_str(r[2])})'
elif symbol == '$':
arg_str = f'substring({arg}, string-length({arg}) - string-length({_make_search_str(r[2])}) +1) ' \
f'= {_make_search_str(r[2])}'
else:
raise ValueError(f'符号不正确:{symbol}')
if arg_str and ignore:
arg_str = f'not({arg_str})'

View File

@ -36,6 +36,7 @@ class DriverOptions(Options):
self._experimental_options = options_dict.get('experimental_options', {})
self._debugger_address = options_dict.get('debugger_address', None)
self.page_load_strategy = options_dict.get('page_load_strategy', 'normal')
self.system_user_path = options_dict.get('system_user_path', False)
for arg in self._arguments:
if arg.startswith('--user-data-dir='):
@ -50,6 +51,7 @@ class DriverOptions(Options):
self.ini_path = None
self.timeouts = {'implicit': 10, 'pageLoad': 30, 'script': 30}
self._debugger_address = '127.0.0.1:9222'
self.system_user_path = False
@property
def driver_path(self):