mirror of
https://gitee.com/g1879/DrissionPage.git
synced 2024-12-10 04:00:23 +08:00
一些修改(+)
增加Settings.browser_connect_timeout属性; 优化关闭标签页逻辑; 修复下载路径设置问题; 点击产生的新标签页下载任务可用原标签页等待; remove_attr()返回元素自身; select各种方法返回元素本身,找不到项时报错;
This commit is contained in:
parent
8d37aa079e
commit
4407a0daa1
@ -65,7 +65,6 @@ class Chromium(object):
|
|||||||
self._drivers = {}
|
self._drivers = {}
|
||||||
self._all_drivers = {}
|
self._all_drivers = {}
|
||||||
self._newest_tab_id = None
|
self._newest_tab_id = None
|
||||||
self._tab_to_close = set()
|
|
||||||
|
|
||||||
self._set = None
|
self._set = None
|
||||||
self._wait = None
|
self._wait = None
|
||||||
@ -204,18 +203,19 @@ class Chromium(object):
|
|||||||
all_tabs = set(self.tab_ids)
|
all_tabs = set(self.tab_ids)
|
||||||
if others:
|
if others:
|
||||||
tabs = all_tabs - tabs
|
tabs = all_tabs - tabs
|
||||||
if len(all_tabs - tabs) <= 0:
|
|
||||||
self.quit()
|
|
||||||
return
|
|
||||||
for tab in tabs:
|
|
||||||
self._close_tab(tab_id=tab)
|
|
||||||
|
|
||||||
def _close_tab(self, tab_id):
|
if len(all_tabs - tabs) > 0:
|
||||||
# self._onTargetDestroyed(targetId=tab)
|
for tab in tabs:
|
||||||
self._tab_to_close.add(tab_id)
|
self._close_tab(tab=tab)
|
||||||
self._driver.run('Target.closeTarget', targetId=tab_id)
|
else:
|
||||||
while tab_id in self._tab_to_close:
|
self.quit()
|
||||||
sleep(.2)
|
|
||||||
|
def _close_tab(self, tab):
|
||||||
|
if isinstance(tab, str):
|
||||||
|
tab = self.get_tab(tab)
|
||||||
|
tab._run_cdp('Target.closeTarget', targetId=tab.tab_id)
|
||||||
|
while tab.driver.is_running and tab.tab_id in self._all_drivers:
|
||||||
|
sleep(.01)
|
||||||
|
|
||||||
def activate_tab(self, id_ind_tab):
|
def activate_tab(self, id_ind_tab):
|
||||||
if isinstance(id_ind_tab, int):
|
if isinstance(id_ind_tab, int):
|
||||||
@ -396,16 +396,14 @@ class Chromium(object):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def _onTargetDestroyed(self, **kwargs):
|
def _onTargetDestroyed(self, **kwargs):
|
||||||
with self._lock:
|
tab_id = kwargs['targetId']
|
||||||
tab_id = kwargs['targetId']
|
self._dl_mgr.clear_tab_info(tab_id)
|
||||||
self._dl_mgr.clear_tab_info(tab_id)
|
for key in [k for k, i in self._frames.items() if i == tab_id]:
|
||||||
for key in [k for k, i in self._frames.items() if i == tab_id]:
|
self._frames.pop(key, None)
|
||||||
self._frames.pop(key, None)
|
for d in self._all_drivers.get(tab_id, tuple()):
|
||||||
for d in self._all_drivers.get(tab_id, tuple()):
|
d.stop()
|
||||||
d.stop()
|
self._drivers.pop(tab_id, None)
|
||||||
self._drivers.pop(tab_id, None)
|
self._all_drivers.pop(tab_id, None)
|
||||||
self._all_drivers.pop(tab_id, None)
|
|
||||||
self._tab_to_close.discard(tab_id)
|
|
||||||
|
|
||||||
def _on_disconnect(self):
|
def _on_disconnect(self):
|
||||||
if not self._disconnect_flag:
|
if not self._disconnect_flag:
|
||||||
|
@ -12,7 +12,7 @@ from .driver import BrowserDriver, Driver
|
|||||||
from .._configs.chromium_options import ChromiumOptions
|
from .._configs.chromium_options import ChromiumOptions
|
||||||
from .._configs.session_options import SessionOptions
|
from .._configs.session_options import SessionOptions
|
||||||
from .._functions.cookies import CookiesList
|
from .._functions.cookies import CookiesList
|
||||||
from .._pages.chromium_base import Timeout
|
from .._pages.chromium_base import Timeout, ChromiumBase
|
||||||
from .._pages.chromium_tab import ChromiumTab
|
from .._pages.chromium_tab import ChromiumTab
|
||||||
from .._pages.mix_tab import MixTab
|
from .._pages.mix_tab import MixTab
|
||||||
from .._units.downloader import DownloadManager
|
from .._units.downloader import DownloadManager
|
||||||
@ -52,7 +52,6 @@ class Chromium(object):
|
|||||||
_none_ele_return_value: bool = ...
|
_none_ele_return_value: bool = ...
|
||||||
_none_ele_value: Any = ...
|
_none_ele_value: Any = ...
|
||||||
_newest_tab_id: Optional[str] = ...
|
_newest_tab_id: Optional[str] = ...
|
||||||
_tab_to_close: set = ...
|
|
||||||
|
|
||||||
def __new__(cls,
|
def __new__(cls,
|
||||||
addr_or_opts: Union[str, int, ChromiumOptions] = None,
|
addr_or_opts: Union[str, int, ChromiumOptions] = None,
|
||||||
@ -194,9 +193,9 @@ class Chromium(object):
|
|||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def _close_tab(self, tab_id: str):
|
def _close_tab(self, tab: Union[ChromiumBase, str]):
|
||||||
"""关闭一个标签页
|
"""关闭一个标签页
|
||||||
:param tab_id: 标签页id
|
:param tab: 标签页对象或id
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -336,7 +336,7 @@ class ChromiumOptions(object):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
def set_address(self, address):
|
def set_address(self, address):
|
||||||
address = address.replace('localhost', '127.0.0.1').lstrip('http://').lstrip('https://')
|
address = address.replace('localhost', '127.0.0.1').lstrip('htps:/')
|
||||||
self._address = address
|
self._address = address
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@ -204,6 +204,8 @@ class ChromiumElement(DrissionElement):
|
|||||||
if (is_checked and uncheck) or (not is_checked and not uncheck):
|
if (is_checked and uncheck) or (not is_checked and not uncheck):
|
||||||
self.click()
|
self.click()
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
def parent(self, level_or_loc=1, index=1, timeout=0):
|
def parent(self, level_or_loc=1, index=1, timeout=0):
|
||||||
return super().parent(level_or_loc, index, timeout=timeout)
|
return super().parent(level_or_loc, index, timeout=timeout)
|
||||||
|
|
||||||
@ -399,6 +401,7 @@ class ChromiumElement(DrissionElement):
|
|||||||
|
|
||||||
def remove_attr(self, name):
|
def remove_attr(self, name):
|
||||||
self._run_js(f'this.removeAttribute("{name}");')
|
self._run_js(f'this.removeAttribute("{name}");')
|
||||||
|
return self
|
||||||
|
|
||||||
def property(self, name):
|
def property(self, name):
|
||||||
try:
|
try:
|
||||||
@ -555,7 +558,7 @@ class ChromiumElement(DrissionElement):
|
|||||||
vals = ''.join([str(i) for i in vals])
|
vals = ''.join([str(i) for i in vals])
|
||||||
self.set.property('value', str(vals))
|
self.set.property('value', str(vals))
|
||||||
self._run_js('this.dispatchEvent(new Event("change", {bubbles: true}));')
|
self._run_js('this.dispatchEvent(new Event("change", {bubbles: true}));')
|
||||||
return
|
return self
|
||||||
|
|
||||||
self.wait.clickable(wait_moved=False, timeout=.5)
|
self.wait.clickable(wait_moved=False, timeout=.5)
|
||||||
if clear and vals not in ('\n', '\ue007'):
|
if clear and vals not in ('\n', '\ue007'):
|
||||||
@ -575,7 +578,7 @@ class ChromiumElement(DrissionElement):
|
|||||||
if by_js:
|
if by_js:
|
||||||
self._run_js("this.value='';")
|
self._run_js("this.value='';")
|
||||||
self._run_js('this.dispatchEvent(new Event("change", {bubbles: true}));')
|
self._run_js('this.dispatchEvent(new Event("change", {bubbles: true}));')
|
||||||
return
|
return self
|
||||||
|
|
||||||
self._input_focus()
|
self._input_focus()
|
||||||
self.input(('\ue009', 'a', '\ue017'), clear=False)
|
self.input(('\ue009', 'a', '\ue017'), clear=False)
|
||||||
|
@ -377,7 +377,7 @@ class ChromiumElement(DrissionElement):
|
|||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def remove_attr(self, name: str) -> None:
|
def remove_attr(self, name: str) -> ChromiumElement:
|
||||||
"""删除元素一个attribute属性
|
"""删除元素一个attribute属性
|
||||||
:param name: 属性名
|
:param name: 属性名
|
||||||
:return: None
|
:return: None
|
||||||
|
@ -15,6 +15,7 @@ from time import perf_counter, sleep
|
|||||||
|
|
||||||
from requests import Session
|
from requests import Session
|
||||||
|
|
||||||
|
from .settings import Settings
|
||||||
from .tools import port_is_using
|
from .tools import port_is_using
|
||||||
from .._configs.options_manage import OptionsManager
|
from .._configs.options_manage import OptionsManager
|
||||||
from ..errors import BrowserConnectError
|
from ..errors import BrowserConnectError
|
||||||
@ -168,8 +169,8 @@ def set_flags(opt):
|
|||||||
dump(states_dict, f)
|
dump(states_dict, f)
|
||||||
|
|
||||||
|
|
||||||
def test_connect(ip, port, timeout=30):
|
def test_connect(ip, port):
|
||||||
end_time = perf_counter() + timeout
|
end_time = perf_counter() + Settings.browser_connect_timeout
|
||||||
s = Session()
|
s = Session()
|
||||||
s.trust_env = False
|
s.trust_env = False
|
||||||
s.keep_alive = False
|
s.keep_alive = False
|
||||||
|
@ -14,6 +14,7 @@ class Settings(object):
|
|||||||
raise_when_wait_failed = False
|
raise_when_wait_failed = False
|
||||||
singleton_tab_obj = True
|
singleton_tab_obj = True
|
||||||
cdp_timeout = 30
|
cdp_timeout = 30
|
||||||
|
browser_connect_timeout = 30
|
||||||
auto_handle_alert = None
|
auto_handle_alert = None
|
||||||
_suffixes_list = str(Path(__file__).parent.absolute() / 'suffixes.dat').replace('\\', '/')
|
_suffixes_list = str(Path(__file__).parent.absolute() / 'suffixes.dat').replace('\\', '/')
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ class Settings(object):
|
|||||||
raise_when_wait_failed: bool = ...
|
raise_when_wait_failed: bool = ...
|
||||||
singleton_tab_obj: bool = ...
|
singleton_tab_obj: bool = ...
|
||||||
cdp_timeout: float = ...
|
cdp_timeout: float = ...
|
||||||
|
browser_connect_timeout: float = ...
|
||||||
auto_handle_alert: Optional[bool] = ...
|
auto_handle_alert: Optional[bool] = ...
|
||||||
_suffixes_list: str = ...
|
_suffixes_list: str = ...
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ class ChromiumPage(ChromiumBase):
|
|||||||
self.browser.activate_tab(id_ind_tab)
|
self.browser.activate_tab(id_ind_tab)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.browser._close_tab(self.tab_id)
|
self.browser._close_tab(self)
|
||||||
|
|
||||||
def close_tabs(self, tabs_or_ids, others=False):
|
def close_tabs(self, tabs_or_ids, others=False):
|
||||||
self.browser.close_tabs(tabs_or_ids=tabs_or_ids, others=others)
|
self.browser.close_tabs(tabs_or_ids=tabs_or_ids, others=others)
|
||||||
|
@ -54,7 +54,7 @@ class ChromiumTab(ChromiumBase):
|
|||||||
if others:
|
if others:
|
||||||
self.browser.close_tabs(self.tab_id, others=True)
|
self.browser.close_tabs(self.tab_id, others=True)
|
||||||
else:
|
else:
|
||||||
self.browser._close_tab(self.tab_id)
|
self.browser._close_tab(self)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def set(self):
|
def set(self):
|
||||||
|
@ -182,7 +182,7 @@ class MixTab(SessionPage, ChromiumTab, BasePage):
|
|||||||
if others:
|
if others:
|
||||||
self.browser.close_tabs(self.tab_id, others=True)
|
self.browser.close_tabs(self.tab_id, others=True)
|
||||||
else:
|
else:
|
||||||
self.browser._close_tab(self.tab_id)
|
self.browser._close_tab(self)
|
||||||
if session and self._session:
|
if session and self._session:
|
||||||
self._session.close()
|
self._session.close()
|
||||||
if self._response is not None:
|
if self._response is not None:
|
||||||
|
@ -232,7 +232,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
|
|||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if self._has_driver:
|
if self._has_driver:
|
||||||
self.browser._close_tab(self.tab_id)
|
self.browser._close_tab(self)
|
||||||
if self._session:
|
if self._session:
|
||||||
self._session.close()
|
self._session.close()
|
||||||
if self._response is not None:
|
if self._response is not None:
|
||||||
|
@ -125,7 +125,18 @@ class Clicker(object):
|
|||||||
if not self._ele.tab._browser._dl_mgr._running:
|
if not self._ele.tab._browser._dl_mgr._running:
|
||||||
self._ele.tab._browser.set.download_path('.')
|
self._ele.tab._browser.set.download_path('.')
|
||||||
|
|
||||||
if new_tab or self._ele.tab._type.endswith('Page'):
|
if self._ele.tab._type.endswith('Page'):
|
||||||
|
obj = browser = self._ele.tab._browser
|
||||||
|
tid = 'browser'
|
||||||
|
# t_settings = TabDownloadSettings(self._ele.owner.tab_id)
|
||||||
|
# b_settings = TabDownloadSettings('browser')
|
||||||
|
# b_settings.rename = t_settings.rename
|
||||||
|
# b_settings.suffix = t_settings.suffix
|
||||||
|
# t_settings.rename = None
|
||||||
|
# t_settings.suffix = None
|
||||||
|
tmp_save_path = str(Path(save_path).absolute()) if save_path else self._ele.owner._tab.download_path
|
||||||
|
|
||||||
|
elif new_tab:
|
||||||
obj = browser = self._ele.tab._browser
|
obj = browser = self._ele.tab._browser
|
||||||
tid = 'browser'
|
tid = 'browser'
|
||||||
t_settings = TabDownloadSettings(self._ele.owner.tab_id)
|
t_settings = TabDownloadSettings(self._ele.owner.tab_id)
|
||||||
@ -150,11 +161,15 @@ class Clicker(object):
|
|||||||
|
|
||||||
browser._dl_mgr.set_flag(tid, True)
|
browser._dl_mgr.set_flag(tid, True)
|
||||||
self.left(by_js=by_js)
|
self.left(by_js=by_js)
|
||||||
r = wait_mission(browser, tid, timeout)
|
m = wait_mission(browser, tid, timeout)
|
||||||
|
|
||||||
if tmp_save_path:
|
if m:
|
||||||
r.path = tmp_save_path
|
if tmp_save_path:
|
||||||
return r
|
m.path = tmp_save_path
|
||||||
|
if new_tab:
|
||||||
|
self._ele.owner.browser._dl_mgr._tab_missions.setdefault(self._ele.owner.tab_id, []).append(m)
|
||||||
|
m.from_tab = self._ele.owner
|
||||||
|
return m
|
||||||
|
|
||||||
def to_upload(self, file_paths, by_js=False):
|
def to_upload(self, file_paths, by_js=False):
|
||||||
self._ele.owner.set.upload_files(file_paths)
|
self._ele.owner.set.upload_files(file_paths)
|
||||||
|
@ -25,7 +25,7 @@ class DownloadManager(object):
|
|||||||
t.when_file_exists = 'rename'
|
t.when_file_exists = 'rename'
|
||||||
|
|
||||||
self._missions = {} # {guid: DownloadMission}
|
self._missions = {} # {guid: DownloadMission}
|
||||||
self._tab_missions = {} # {tab_id: DownloadMission}
|
self._tab_missions = {} # {tab_id: [DownloadMission, ...]}
|
||||||
self._flags = {} # {tab_id: [bool, DownloadMission]}
|
self._flags = {} # {tab_id: [bool, DownloadMission]}
|
||||||
|
|
||||||
self._running = False
|
self._running = False
|
||||||
@ -67,8 +67,11 @@ class DownloadManager(object):
|
|||||||
if mission.state not in ('canceled', 'skipped'):
|
if mission.state not in ('canceled', 'skipped'):
|
||||||
mission.state = state
|
mission.state = state
|
||||||
mission.final_path = final_path
|
mission.final_path = final_path
|
||||||
if mission.tab_id in self._tab_missions and mission.id in self._tab_missions[mission.tab_id]:
|
if mission.tab_id in self._tab_missions and mission in self._tab_missions[mission.tab_id]:
|
||||||
self._tab_missions[mission.tab_id].remove(mission.id)
|
self._tab_missions[mission.tab_id].remove(mission)
|
||||||
|
if (mission.from_tab and mission.from_tab in self._tab_missions
|
||||||
|
and mission in self._tab_missions[mission.from_tab]):
|
||||||
|
self._tab_missions[mission.from_tab].remove(mission)
|
||||||
self._missions.pop(mission.id, None)
|
self._missions.pop(mission.id, None)
|
||||||
mission._is_done = True
|
mission._is_done = True
|
||||||
|
|
||||||
@ -96,8 +99,9 @@ class DownloadManager(object):
|
|||||||
def _onDownloadWillBegin(self, **kwargs):
|
def _onDownloadWillBegin(self, **kwargs):
|
||||||
guid = kwargs['guid']
|
guid = kwargs['guid']
|
||||||
tab_id = self._browser._frames.get(kwargs['frameId'], 'browser')
|
tab_id = self._browser._frames.get(kwargs['frameId'], 'browser')
|
||||||
|
tab = tab_id if tab_id in TabDownloadSettings.TABS else 'browser'
|
||||||
|
|
||||||
settings = TabDownloadSettings(tab_id if tab_id in TabDownloadSettings.TABS else 'browser')
|
settings = TabDownloadSettings(tab)
|
||||||
if settings.rename:
|
if settings.rename:
|
||||||
if settings.suffix is not None:
|
if settings.suffix is not None:
|
||||||
name = f'{settings.rename}.{settings.suffix}' if settings.suffix else settings.rename
|
name = f'{settings.rename}.{settings.suffix}' if settings.suffix else settings.rename
|
||||||
@ -132,15 +136,15 @@ class DownloadManager(object):
|
|||||||
m = DownloadMission(self, tab_id, guid, settings.path, name, kwargs['url'], self._browser.download_path)
|
m = DownloadMission(self, tab_id, guid, settings.path, name, kwargs['url'], self._browser.download_path)
|
||||||
self._missions[guid] = m
|
self._missions[guid] = m
|
||||||
|
|
||||||
if self.get_flag(tab_id) is False: # 取消该任务
|
if self.get_flag(tab) is False: # 取消该任务
|
||||||
self.cancel(m)
|
self.cancel(m)
|
||||||
elif skip:
|
elif skip:
|
||||||
self.skip(m)
|
self.skip(m)
|
||||||
else:
|
else:
|
||||||
self._tab_missions.setdefault(tab_id, []).append(m)
|
self._tab_missions.setdefault(tab_id, []).append(m)
|
||||||
|
|
||||||
if self.get_flag(tab_id) is not None:
|
if self.get_flag(tab) is not None:
|
||||||
self._flags[tab_id] = m
|
self._flags[tab] = m
|
||||||
|
|
||||||
def _onDownloadProgress(self, **kwargs):
|
def _onDownloadProgress(self, **kwargs):
|
||||||
if kwargs['guid'] in self._missions:
|
if kwargs['guid'] in self._missions:
|
||||||
@ -204,6 +208,7 @@ class DownloadMission(object):
|
|||||||
self._mgr = mgr
|
self._mgr = mgr
|
||||||
self.url = url
|
self.url = url
|
||||||
self.tab_id = tab_id
|
self.tab_id = tab_id
|
||||||
|
self.from_tab = None
|
||||||
self.id = _id
|
self.id = _id
|
||||||
self.path = path
|
self.path = path
|
||||||
self.name = name
|
self.name = name
|
||||||
|
@ -141,6 +141,7 @@ class TabDownloadSettings(object):
|
|||||||
|
|
||||||
class DownloadMission(object):
|
class DownloadMission(object):
|
||||||
tab_id: str = ...
|
tab_id: str = ...
|
||||||
|
from_tab: Optional[str] = ...
|
||||||
_mgr: DownloadManager = ...
|
_mgr: DownloadManager = ...
|
||||||
url: str = ...
|
url: str = ...
|
||||||
id: str = ...
|
id: str = ...
|
||||||
|
@ -32,8 +32,7 @@ class SelectElement(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def selected_option(self):
|
def selected_option(self):
|
||||||
ele = self._ele._run_js('return this.options[this.selectedIndex];')
|
return self._ele._run_js('return this.options[this.selectedIndex];')
|
||||||
return ele
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def selected_options(self):
|
def selected_options(self):
|
||||||
@ -54,6 +53,7 @@ class SelectElement(object):
|
|||||||
i._run_js(f'this.selected={mode};')
|
i._run_js(f'this.selected={mode};')
|
||||||
if change:
|
if change:
|
||||||
self._dispatch_change()
|
self._dispatch_change()
|
||||||
|
return self._ele
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
if not self.is_multi:
|
if not self.is_multi:
|
||||||
@ -73,7 +73,7 @@ class SelectElement(object):
|
|||||||
return self._by_loc(locator, timeout)
|
return self._by_loc(locator, timeout)
|
||||||
|
|
||||||
def by_option(self, option):
|
def by_option(self, option):
|
||||||
self._select_options(option, 'true')
|
return self._select_options(option, 'true')
|
||||||
|
|
||||||
def cancel_by_text(self, text, timeout=None):
|
def cancel_by_text(self, text, timeout=None):
|
||||||
return self._select(text, 'text', True, timeout)
|
return self._select(text, 'text', True, timeout)
|
||||||
@ -88,19 +88,17 @@ class SelectElement(object):
|
|||||||
return self._by_loc(locator, timeout, True)
|
return self._by_loc(locator, timeout, True)
|
||||||
|
|
||||||
def cancel_by_option(self, option):
|
def cancel_by_option(self, option):
|
||||||
self._select_options(option, 'false')
|
return self._select_options(option, 'false')
|
||||||
|
|
||||||
def _by_loc(self, loc, timeout=None, cancel=False):
|
def _by_loc(self, loc, timeout=None, cancel=False):
|
||||||
eles = self._ele.eles(loc, timeout)
|
eles = self._ele.eles(loc, timeout)
|
||||||
if not eles:
|
if not eles:
|
||||||
return False
|
raise RuntimeError('没有找到指定选项。')
|
||||||
|
|
||||||
mode = 'false' if cancel else 'true'
|
mode = 'false' if cancel else 'true'
|
||||||
if self.is_multi:
|
if not self.is_multi:
|
||||||
self._select_options(eles, mode)
|
eles = eles[0]
|
||||||
else:
|
return self._select_options(eles, mode)
|
||||||
self._select_options(eles[0], mode)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _select(self, condition, para_type='text', cancel=False, timeout=None):
|
def _select(self, condition, para_type='text', cancel=False, timeout=None):
|
||||||
if not self.is_multi and isinstance(condition, (list, tuple)):
|
if not self.is_multi and isinstance(condition, (list, tuple)):
|
||||||
@ -117,7 +115,6 @@ class SelectElement(object):
|
|||||||
return self._index(condition, mode, timeout)
|
return self._index(condition, mode, timeout)
|
||||||
|
|
||||||
def _text_value(self, condition, para_type, mode, timeout):
|
def _text_value(self, condition, para_type, mode, timeout):
|
||||||
ok = False
|
|
||||||
text_len = len(condition)
|
text_len = len(condition)
|
||||||
eles = []
|
eles = []
|
||||||
end_time = perf_counter() + timeout
|
end_time = perf_counter() + timeout
|
||||||
@ -128,34 +125,22 @@ class SelectElement(object):
|
|||||||
eles = [i for i in self.options if i.attr('value') in condition]
|
eles = [i for i in self.options if i.attr('value') in condition]
|
||||||
|
|
||||||
if len(eles) >= text_len:
|
if len(eles) >= text_len:
|
||||||
ok = True
|
return self._select_options(eles, mode)
|
||||||
break
|
|
||||||
sleep(.01)
|
sleep(.01)
|
||||||
|
|
||||||
if ok:
|
raise RuntimeError('没有找到指定选项。')
|
||||||
self._select_options(eles, mode)
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _index(self, condition, mode, timeout):
|
def _index(self, condition, mode, timeout):
|
||||||
ok = False
|
|
||||||
condition = [int(i) for i in condition]
|
condition = [int(i) for i in condition]
|
||||||
text_len = abs(max(condition, key=abs))
|
text_len = abs(max(condition, key=abs))
|
||||||
end_time = perf_counter() + timeout
|
end_time = perf_counter() + timeout
|
||||||
while perf_counter() < end_time:
|
while perf_counter() < end_time:
|
||||||
if len(self.options) >= text_len:
|
if len(self.options) >= text_len:
|
||||||
ok = True
|
eles = self.options
|
||||||
break
|
eles = [eles[i - 1] if i > 0 else eles[i] for i in condition]
|
||||||
|
return self._select_options(eles, mode)
|
||||||
sleep(.01)
|
sleep(.01)
|
||||||
|
raise RuntimeError('没有找到指定选项。')
|
||||||
if ok:
|
|
||||||
eles = self.options
|
|
||||||
eles = [eles[i - 1] if i > 0 else eles[i] for i in condition]
|
|
||||||
self._select_options(eles, mode)
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _select_options(self, option, mode):
|
def _select_options(self, option, mode):
|
||||||
if isinstance(option, (list, tuple, set)):
|
if isinstance(option, (list, tuple, set)):
|
||||||
@ -167,6 +152,7 @@ class SelectElement(object):
|
|||||||
else:
|
else:
|
||||||
option._run_js(f'this.selected={mode};')
|
option._run_js(f'this.selected={mode};')
|
||||||
self._dispatch_change()
|
self._dispatch_change()
|
||||||
|
return self._ele
|
||||||
|
|
||||||
def _dispatch_change(self):
|
def _dispatch_change(self):
|
||||||
self._ele._run_js('this.dispatchEvent(new CustomEvent("change", {bubbles: true}));')
|
self._ele._run_js('this.dispatchEvent(new CustomEvent("change", {bubbles: true}));')
|
||||||
|
@ -20,11 +20,11 @@ class SelectElement(object):
|
|||||||
|
|
||||||
def __call__(self,
|
def __call__(self,
|
||||||
text_or_index: Union[str, int, list, tuple],
|
text_or_index: Union[str, int, list, tuple],
|
||||||
timeout: float = None) -> bool:
|
timeout: float = None) -> ChromiumElement:
|
||||||
"""选定下拉列表中子元素
|
"""选定下拉列表中子元素
|
||||||
:param text_or_index: 根据文本、值选或序号择选项,若允许多选,传入list或tuple可多选
|
:param text_or_index: 根据文本、值选或序号择选项,若允许多选,传入list或tuple可多选
|
||||||
:param timeout: 超时时间(秒),不输入默认实用页面超时时间
|
:param timeout: 超时时间(秒),不输入默认实用页面超时时间
|
||||||
:return: None
|
:return: <select>元素对象
|
||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
@ -48,122 +48,124 @@ class SelectElement(object):
|
|||||||
"""返回所有被选中的<option>元素列表"""
|
"""返回所有被选中的<option>元素列表"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def all(self) -> None:
|
def all(self) -> ChromiumElement:
|
||||||
"""全选"""
|
"""全选"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def invert(self) -> None:
|
def invert(self) -> ChromiumElement:
|
||||||
"""反选"""
|
"""反选"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def clear(self) -> None:
|
def clear(self) -> ChromiumElement:
|
||||||
"""清除所有已选项"""
|
"""清除所有已选项"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def by_text(self,
|
def by_text(self,
|
||||||
text: Union[str, list, tuple],
|
text: Union[str, list, tuple],
|
||||||
timeout: float = None) -> bool:
|
timeout: float = None) -> ChromiumElement:
|
||||||
"""此方法用于根据text值选择项。当元素是多选列表时,可以接收list或tuple
|
"""此方法用于根据text值选择项。当元素是多选列表时,可以接收list或tuple
|
||||||
:param text: text属性值,传入list或tuple可选择多项
|
:param text: text属性值,传入list或tuple可选择多项
|
||||||
:param timeout: 超时时间(秒),为None默认使用页面超时时间
|
:param timeout: 超时时间(秒),为None默认使用页面超时时间
|
||||||
:return: 是否选择成功
|
:return: <select>元素对象
|
||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def by_value(self,
|
def by_value(self,
|
||||||
value: Union[str, list, tuple],
|
value: Union[str, list, tuple],
|
||||||
timeout: float = None) -> bool:
|
timeout: float = None) -> ChromiumElement:
|
||||||
"""此方法用于根据value值选择项。当元素是多选列表时,可以接收list或tuple
|
"""此方法用于根据value值选择项。当元素是多选列表时,可以接收list或tuple
|
||||||
:param value: value属性值,传入list或tuple可选择多项
|
:param value: value属性值,传入list或tuple可选择多项
|
||||||
:param timeout: 超时时间,为None默认使用页面超时时间
|
:param timeout: 超时时间,为None默认使用页面超时时间
|
||||||
:return: 是否选择成功
|
:return: <select>元素对象
|
||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def by_index(self,
|
def by_index(self,
|
||||||
index: Union[int, list, tuple],
|
index: Union[int, list, tuple],
|
||||||
timeout: float = None) -> bool:
|
timeout: float = None) -> ChromiumElement:
|
||||||
"""此方法用于根据index值选择项。当元素是多选列表时,可以接收list或tuple
|
"""此方法用于根据index值选择项。当元素是多选列表时,可以接收list或tuple
|
||||||
:param index: 序号,从1开始,可传入负数获取倒数第几个,传入list或tuple可选择多项
|
:param index: 序号,从1开始,可传入负数获取倒数第几个,传入list或tuple可选择多项
|
||||||
:param timeout: 超时时间,为None默认使用页面超时时间
|
:param timeout: 超时时间,为None默认使用页面超时时间
|
||||||
:return: 是否选择成功
|
:return: <select>元素对象
|
||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def by_locator(self,
|
def by_locator(self,
|
||||||
locator: Union[Tuple[str, str], str],
|
locator: Union[Tuple[str, str], str],
|
||||||
timeout: float = None) -> bool:
|
timeout: float = None) -> ChromiumElement:
|
||||||
"""用定位符选择指定的项
|
"""用定位符选择指定的项
|
||||||
:param locator: 定位符
|
:param locator: 定位符
|
||||||
:param timeout: 超时时间
|
:param timeout: 超时时间
|
||||||
:return: 是否选择成功
|
:return: <select>元素对象
|
||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def by_option(self, option: Union[ChromiumElement, List[ChromiumElement], Tuple[ChromiumElement]]) -> None:
|
def by_option(self,
|
||||||
|
option: Union[ChromiumElement, List[ChromiumElement], Tuple[ChromiumElement]]) -> ChromiumElement:
|
||||||
"""选中单个或多个<option>元素
|
"""选中单个或多个<option>元素
|
||||||
:param option: <option>元素或它们组成的列表
|
:param option: <option>元素或它们组成的列表
|
||||||
:return: None
|
:return: <select>元素对象
|
||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def cancel_by_text(self,
|
def cancel_by_text(self,
|
||||||
text: Union[str, list, tuple],
|
text: Union[str, list, tuple],
|
||||||
timeout: float = None) -> bool:
|
timeout: float = None) -> ChromiumElement:
|
||||||
"""此方法用于根据text值取消选择项。当元素是多选列表时,可以接收list或tuple
|
"""此方法用于根据text值取消选择项。当元素是多选列表时,可以接收list或tuple
|
||||||
:param text: 文本,传入list或tuple可取消多项
|
:param text: 文本,传入list或tuple可取消多项
|
||||||
:param timeout: 超时时间,不输入默认实用页面超时时间
|
:param timeout: 超时时间,不输入默认实用页面超时时间
|
||||||
:return: 是否取消成功
|
:return: <select>元素对象
|
||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def cancel_by_value(self,
|
def cancel_by_value(self,
|
||||||
value: Union[str, list, tuple],
|
value: Union[str, list, tuple],
|
||||||
timeout: float = None) -> bool:
|
timeout: float = None) -> ChromiumElement:
|
||||||
"""此方法用于根据value值取消选择项。当元素是多选列表时,可以接收list或tuple
|
"""此方法用于根据value值取消选择项。当元素是多选列表时,可以接收list或tuple
|
||||||
:param value: value属性值,传入list或tuple可取消多项
|
:param value: value属性值,传入list或tuple可取消多项
|
||||||
:param timeout: 超时时间,不输入默认实用页面超时时间
|
:param timeout: 超时时间,不输入默认实用页面超时时间
|
||||||
:return: 是否取消成功
|
:return: <select>元素对象
|
||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def cancel_by_index(self,
|
def cancel_by_index(self,
|
||||||
index: Union[int, list, tuple],
|
index: Union[int, list, tuple],
|
||||||
timeout: float = None) -> bool:
|
timeout: float = None) -> ChromiumElement:
|
||||||
"""此方法用于根据index值取消选择项。当元素是多选列表时,可以接收list或tuple
|
"""此方法用于根据index值取消选择项。当元素是多选列表时,可以接收list或tuple
|
||||||
:param index: 序号,从1开始,可传入负数获取倒数第几个,传入list或tuple可取消多项
|
:param index: 序号,从1开始,可传入负数获取倒数第几个,传入list或tuple可取消多项
|
||||||
:param timeout: 超时时间,不输入默认实用页面超时时间
|
:param timeout: 超时时间,不输入默认实用页面超时时间
|
||||||
:return: 是否取消成功
|
:return: <select>元素对象
|
||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def cancel_by_locator(self,
|
def cancel_by_locator(self,
|
||||||
locator: Union[Tuple[str, str], str],
|
locator: Union[Tuple[str, str], str],
|
||||||
timeout: float = None) -> bool:
|
timeout: float = None) -> ChromiumElement:
|
||||||
"""用定位符取消选择指定的项
|
"""用定位符取消选择指定的项
|
||||||
:param locator: 定位符
|
:param locator: 定位符
|
||||||
:param timeout: 超时时间
|
:param timeout: 超时时间
|
||||||
:return: 是否选择成功
|
:return: <select>元素对象
|
||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def cancel_by_option(self,
|
def cancel_by_option(self,
|
||||||
option: Union[ChromiumElement, List[ChromiumElement], Tuple[ChromiumElement]]) -> None:
|
option: Union[ChromiumElement, List[ChromiumElement],
|
||||||
|
Tuple[ChromiumElement]]) -> ChromiumElement:
|
||||||
"""取消选中单个或多个<option>元素
|
"""取消选中单个或多个<option>元素
|
||||||
:param option: <option>元素或它们组成的列表
|
:param option: <option>元素或它们组成的列表
|
||||||
:return: None
|
:return: <select>元素对象
|
||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def _by_loc(self,
|
def _by_loc(self,
|
||||||
loc: Union[str, Tuple[str, str]],
|
loc: Union[str, Tuple[str, str]],
|
||||||
timeout: float = None,
|
timeout: float = None,
|
||||||
cancel: bool = False) -> bool:
|
cancel: bool = False) -> ChromiumElement:
|
||||||
"""用定位符取消选择指定的项
|
"""用定位符取消选择指定的项
|
||||||
:param loc: 定位符
|
:param loc: 定位符
|
||||||
:param timeout: 超时时间
|
:param timeout: 超时时间
|
||||||
:param cancel: 是否取消选择
|
:param cancel: 是否取消选择
|
||||||
:return: 是否选择成功
|
:return: <select>元素对象
|
||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
@ -171,12 +173,12 @@ class SelectElement(object):
|
|||||||
condition: Union[str, int, list, tuple] = None,
|
condition: Union[str, int, list, tuple] = None,
|
||||||
para_type: str = 'text',
|
para_type: str = 'text',
|
||||||
cancel: bool = False,
|
cancel: bool = False,
|
||||||
timeout: float = None) -> bool:
|
timeout: float = None) -> ChromiumElement:
|
||||||
"""选定或取消选定下拉列表中子元素
|
"""选定或取消选定下拉列表中子元素
|
||||||
:param condition: 根据文本、值选或序号择选项,若允许多选,传入list或tuple可多选
|
:param condition: 根据文本、值选或序号择选项,若允许多选,传入list或tuple可多选
|
||||||
:param para_type: 参数类型,可选 'text'、'value'、'index'
|
:param para_type: 参数类型,可选 'text'、'value'、'index'
|
||||||
:param cancel: 是否取消选择
|
:param cancel: 是否取消选择
|
||||||
:return: 是否选择成功
|
:return: <select>元素对象
|
||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
@ -184,31 +186,32 @@ class SelectElement(object):
|
|||||||
condition: Union[list, set],
|
condition: Union[list, set],
|
||||||
para_type: str,
|
para_type: str,
|
||||||
mode: str,
|
mode: str,
|
||||||
timeout: float) -> bool:
|
timeout: float) -> ChromiumElement:
|
||||||
"""执行text和value搜索
|
"""执行text和value搜索
|
||||||
:param condition: 条件set
|
:param condition: 条件set
|
||||||
:param para_type: 参数类型,可选 'text'、'value'
|
:param para_type: 参数类型,可选 'text'、'value'
|
||||||
:param mode: 'true' 或 'false'
|
:param mode: 'true' 或 'false'
|
||||||
:param timeout: 超时时间
|
:param timeout: 超时时间
|
||||||
:return: 是否选择成功
|
:return: <select>元素对象
|
||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def _index(self, condition: set, mode: str, timeout: float) -> bool:
|
def _index(self, condition: set, mode: str, timeout: float) -> ChromiumElement:
|
||||||
"""执行index搜索
|
"""执行index搜索
|
||||||
:param condition: 条件set
|
:param condition: 条件set
|
||||||
:param mode: 'true' 或 'false'
|
:param mode: 'true' 或 'false'
|
||||||
:param timeout: 超时时间
|
:param timeout: 超时时间
|
||||||
:return: 是否选择成功
|
:return: <select>元素对象
|
||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def _select_options(self, option: Union[ChromiumElement, List[ChromiumElement], Tuple[ChromiumElement]],
|
def _select_options(self,
|
||||||
mode: str) -> None:
|
option: Union[ChromiumElement, List[ChromiumElement], Tuple[ChromiumElement]],
|
||||||
|
mode: str) -> ChromiumElement:
|
||||||
"""选中或取消某个选项
|
"""选中或取消某个选项
|
||||||
:param option: options元素对象
|
:param option: options元素对象
|
||||||
:param mode: 选中还是取消
|
:param mode: 选中还是取消
|
||||||
:return: None
|
:return: <select>元素对象
|
||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
|
@ -271,7 +271,7 @@ class ChromiumPageSetter(TabSetter):
|
|||||||
self._owner._DownloadKit.set.save_path(path)
|
self._owner._DownloadKit.set.save_path(path)
|
||||||
|
|
||||||
def download_file_name(self, name=None, suffix=None):
|
def download_file_name(self, name=None, suffix=None):
|
||||||
super().download_file_name(name=name, suffix=suffix)
|
# super().download_file_name(name=name, suffix=suffix)
|
||||||
self._owner.browser.set.download_file_name(name, suffix)
|
self._owner.browser.set.download_file_name(name, suffix)
|
||||||
|
|
||||||
|
|
||||||
|
@ -270,6 +270,9 @@ class ChromiumPageWaiter(TabWaiter):
|
|||||||
def new_tab(self, timeout=None, raise_err=None):
|
def new_tab(self, timeout=None, raise_err=None):
|
||||||
return self._owner.browser.wait.new_tab(timeout=timeout, raise_err=raise_err)
|
return self._owner.browser.wait.new_tab(timeout=timeout, raise_err=raise_err)
|
||||||
|
|
||||||
|
def download_begin(self, timeout=None, cancel_it=False):
|
||||||
|
return self._owner.browser.wait.download_begin(timeout=timeout, cancel_it=cancel_it)
|
||||||
|
|
||||||
def all_downloads_done(self, timeout=None, cancel_if_timeout=True):
|
def all_downloads_done(self, timeout=None, cancel_if_timeout=True):
|
||||||
return self._owner.browser.wait.downloads_done(timeout=timeout, cancel_if_timeout=cancel_if_timeout)
|
return self._owner.browser.wait.downloads_done(timeout=timeout, cancel_if_timeout=cancel_if_timeout)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user