完善注释

This commit is contained in:
g1879 2020-08-13 11:34:16 +08:00
parent 9d28932f45
commit 16847f829d
8 changed files with 177 additions and 60 deletions

View File

@ -131,16 +131,27 @@ def get_loc_from_str(loc: str) -> tuple:
def _make_xpath_str(tag: str, arg: str, val: str, mode: str = 'fuzzy') -> str:
"""生成xpath语句"""
"""生成xpath语句 \n
:param tag: 标签名
:param arg: 属性名
:param val: 属性值
:param mode: 'exact' 'fuzzy'对应精确或模糊查找
:return: xpath字符串
"""
tag_name = '' if tag == '*' else f'name()="{tag}" and '
if mode == 'exact':
return f'//*[{tag_name}{arg}={_make_search_str(val)}]'
else:
elif mode == 'fuzzy':
return f"//*[{tag_name}contains({arg},{_make_search_str(val)})]"
else:
raise ValueError("Argument mode can only be 'exact' or 'fuzzy'.")
def _make_search_str(search_str: str) -> str:
""""转义,不知何故不能直接用\""""
""""转义,不知何故不能直接用\ \n
:param search_str: 查询字符串
:return: "转义后的字符串
"""
parts = search_str.split('"')
parts_num = len(parts)
search_str = 'concat('
@ -151,8 +162,11 @@ def _make_search_str(search_str: str) -> str:
return search_str
def translate_loc_to_xpath(loc) -> tuple:
"""把By类型转为xpath或css selector"""
def translate_loc_to_xpath(loc: tuple) -> tuple:
"""把By类型的loc元组转换为css selector或xpath类型的 \n
:param loc: By类型的loc元组
:return: css selector或xpath类型的loc元组
"""
loc_by = 'xpath'
loc_str = None
if loc[0] == 'xpath':

View File

@ -17,7 +17,7 @@ class OptionsManager(object):
"""管理配置文件内容的类"""
def __init__(self, path: str = None):
"""初始化,读取配置文件,如没有设置临时文件夹,则设置并新建
"""初始化,读取配置文件,如没有设置临时文件夹,则设置并新建 \n
:param path: ini文件的路径默认读取模块文件夹下的
"""
self.path = path or Path(__file__).parent / 'configs.ini'
@ -30,7 +30,11 @@ class OptionsManager(object):
self.save()
def get_value(self, section: str, item: str) -> Any:
"""获取配置的值"""
"""获取配置的值 \n
:param section: 段名
:param item: 项名
:return: 项值
"""
try:
return eval(self._conf.get(section, item))
except SyntaxError:
@ -39,7 +43,10 @@ class OptionsManager(object):
return None
def get_option(self, section: str) -> dict:
"""把section内容以字典方式返回"""
"""把section内容以字典方式返回 \n
:param section: 段名
:return: 段内容生成的字典
"""
items = self._conf.items(section)
option = dict()
for j in items:
@ -50,14 +57,19 @@ class OptionsManager(object):
return option
def set_item(self, section: str, item: str, value: Any):
"""设置配置值"""
"""设置配置值 \n
:param section: 段名
:param item: 项名
:param value: 项值
:return: 当前对象
"""
self._conf.set(section, item, str(value))
return self
def save(self, path: str = None):
"""保存配置文件
"""保存配置文件 \n
:param path: ini文件的路径默认保存到模块文件夹下的
:return: None
:return: 当前对象
"""
path = path or Path(__file__).parent / 'configs.ini'
self._conf.write(open(path, 'w', encoding='utf-8'))
@ -66,7 +78,9 @@ class OptionsManager(object):
class DriverOptions(Options):
def __init__(self, read_file=True):
"""初始化,默认从文件读取设置"""
"""初始化,默认从文件读取设置 \n
:param read_file: 是否从默认ini文件中读取配置信息
"""
super().__init__()
self._driver_path = None
if read_file:
@ -89,9 +103,9 @@ class DriverOptions(Options):
return self.binary_location
def save(self, path: str = None):
"""保存设置到文件
"""保存设置到文件 \n
:param path: ini文件的路径默认保存到模块文件夹下的
:return: None
:return: 当前对象
"""
om = OptionsManager()
options = _chrome_options_to_dict(self)
@ -104,9 +118,9 @@ class DriverOptions(Options):
return self
def remove_argument(self, value: str):
"""移除一个设置
"""移除一个argument项 \n
:param value: 设置项名有值的设置项传入设置名称即可
:return: None
:return: 当前对象
"""
del_list = []
for argument in self._arguments:
@ -117,22 +131,27 @@ class DriverOptions(Options):
return self
def remove_experimental_option(self, key: str):
"""移除一个实验设置传入key值删除"""
"""移除一个实验设置传入key值删除 \n
:param key: 实验设置的名称
:return: 当前对象
"""
if key in self._experimental_options:
self._experimental_options.pop(key)
return self
def remove_all_extensions(self):
"""移除所有插件
因插件是以整个文件储存难以移除其中一个故如须设置则全部移除再重设"""
"""移除所有插件 \n
因插件是以整个文件储存难以移除其中一个故如须设置则全部移除再重设
:return: 当前对象
"""
self._extensions = []
return self
def set_argument(self, arg: str, value: Union[bool, str]):
"""设置浏览器配置argument属性
"""设置浏览器配置argument属性 \n
:param arg: 属性名
:param value: 属性值有值的属性传入值没有的传入bool
:return: None
:return: 当前对象
"""
self.remove_argument(arg)
if value:
@ -141,27 +160,45 @@ class DriverOptions(Options):
return self
def set_headless(self, on_off: bool = True):
"""设置headless"""
"""设置是否隐藏浏览器界面 \n
:param on_off: 开或关
:return: 当前对象
"""
return self.set_argument('--headless', on_off)
def set_no_imgs(self, on_off: bool = True):
"""设置是否加载图片"""
"""设置是否加载图片 \n
:param on_off: 开或关
:return: 当前对象
"""
return self.set_argument('--blink-settings=imagesEnabled=false', on_off)
def set_no_js(self, on_off: bool = True):
"""设置禁用js"""
"""设置是否禁用js \n
:param on_off: 开或关
:return: 当前对象
"""
return self.set_argument('--disable-javascript', on_off)
def set_mute(self, on_off: bool = True):
"""设置静音"""
"""设置是否静音 \n
:param on_off: 开或关
:return: 当前对象
"""
return self.set_argument('--mute-audio', on_off)
def set_user_agent(self, user_agent: str):
"""设置user agent"""
"""设置user agent \n
:param user_agent: user agent文本
:return: 当前对象
"""
return self.set_argument('user-agent', user_agent)
def set_proxy(self, proxy: str):
"""设置代理"""
"""设置代理 \n
:param proxy: 代理url和端口
:return: 当前对象
"""
return self.set_argument('--proxy-server', proxy)
def set_paths(self,
@ -171,14 +208,14 @@ class DriverOptions(Options):
download_path: str = None,
user_data_path: str = None,
cache_path: str = None):
"""简易设置路径函数
"""快捷的路径设置函数 \n
:param driver_path: chromedriver.exe路径
:param chrome_path: chrome.exe路径
:param debugger_address: 调试浏览器地址127.0.0.1:9222
:param download_path: 下载文件路径
:param user_data_path: 用户数据路径
:param cache_path: 缓存路径
:return: None
:return: 当前对象
"""
def format_path(path: str) -> str:
@ -200,7 +237,10 @@ class DriverOptions(Options):
def _dict_to_chrome_options(options: dict) -> Options:
"""从传入的字典获取浏览器设置返回ChromeOptions对象"""
"""从传入的字典获取浏览器设置返回ChromeOptions对象 \n
:param options: 配置信息字典
:return: 保存浏览器配置的ChromeOptions对象
"""
chrome_options = webdriver.ChromeOptions()
if 'debugger_address' in options and options['debugger_address']:
# 控制已打开的浏览器
@ -238,6 +278,10 @@ def _dict_to_chrome_options(options: dict) -> Options:
def _chrome_options_to_dict(options: Union[dict, DriverOptions, None]) -> Union[dict, None]:
"""把chrome配置对象转换为字典 \n
:param options: chrome配置对象字典或DriverOptions对象
:return: 配置字典
"""
if options is None or isinstance(options, dict):
return options

View File

@ -26,7 +26,7 @@ class Drission(object):
session_options: dict = None,
ini_path: str = None,
proxy: dict = None):
"""初始化配置信息但不生成session和driver实例
"""初始化配置信息但不生成session和driver实例 \n
:param driver_options: chrome设置Options类或设置字典
:param session_options: session设置
:param ini_path: ini文件路径'
@ -52,7 +52,7 @@ class Drission(object):
@property
def session(self) -> HTMLSession:
"""获取HTMLSession对象"""
"""返回HTMLSession对象如为None则按配置信息创建"""
if self._session is None:
self._session = HTMLSession()
attrs = ['headers', 'cookies', 'auth', 'proxies', 'hooks', 'params', 'verify',
@ -67,7 +67,7 @@ class Drission(object):
@property
def driver(self) -> WebDriver:
"""获取WebDriver对象按传入配置信息初始化"""
"""返回WebDriver对象如为None则按配置信息创建"""
if self._driver is None:
if isinstance(self._driver_options, dict):
options = _dict_to_chrome_options(self._driver_options)
@ -92,22 +92,33 @@ class Drission(object):
@property
def driver_options(self) -> dict:
"""返回driver配置信息"""
return self._driver_options
@property
def session_options(self) -> dict:
"""返回session配置信息"""
return self._session_options
@session_options.setter
def session_options(self, value: dict):
def session_options(self, value: dict) -> None:
"""设置session配置
:param value: session配置字典
:return: None
"""
self._session_options = value
@property
def proxy(self) -> Union[None, dict]:
"""返回代理信息"""
return self._proxy
@proxy.setter
def proxy(self, proxies: dict = None):
def proxy(self, proxies: dict = None) -> None:
"""设置代理信息 \n
:param proxies: 代理信息字典
:return: None
"""
self._proxy = proxies
if self._session:
self._session.proxies = proxies
@ -121,9 +132,15 @@ class Drission(object):
for cookie in cookies:
self._ensure_add_cookie(cookie)
def cookies_to_session(self, copy_user_agent: bool = False, driver: WebDriver = None, session: Session = None) \
-> None:
"""把driver的cookies复制到session"""
def cookies_to_session(self, copy_user_agent: bool = False,
driver: WebDriver = None,
session: Session = None) -> None:
"""把driver对象的cookies复制到session对象 \n
:param copy_user_agent: 是否复制ua信息
:param driver: 来源driver对象
:param session: 目标session对象
:return: None
"""
driver = driver or self.driver
session = session or self.session
if copy_user_agent:
@ -131,8 +148,15 @@ class Drission(object):
for cookie in driver.get_cookies():
session.cookies.set(cookie['name'], cookie['value'], domain=cookie['domain'])
def cookies_to_driver(self, url: str, driver: WebDriver = None, session: Session = None) -> None:
"""把session的cookies复制到driver"""
def cookies_to_driver(self, url: str,
driver: WebDriver = None,
session: Session = None) -> None:
"""把session对象的cookies复制到driver对象 \n
:param url: 作用域
:param driver: 目标driver对象
:param session: 来源session对象
:return: None
"""
driver = driver or self.driver
session = session or self.session
domain = urlparse(url).netloc
@ -146,7 +170,12 @@ class Drission(object):
self._ensure_add_cookie(cookie_data, driver=driver)
def _ensure_add_cookie(self, cookie, override_domain=None, driver=None) -> None:
"""添加cookie到driver"""
"""添加cookie到driver \n
:param cookie: 要添加的cookie
:param override_domain: 覆盖作用域
:param driver: 操作的driver对象
:return: None
"""
driver = driver or self.driver
if override_domain:
cookie['domain'] = override_domain
@ -171,8 +200,12 @@ class Drission(object):
raise WebDriverException(f"Couldn't add the following cookie to the webdriver\n{cookie}\n")
def _is_cookie_in_driver(self, cookie, driver=None) -> bool:
"""检查cookie是否已经在driver里
只检查namevaluedomain检查domain时比较宽"""
"""检查cookie是否已经在driver里 \n
只检查namevaluedomain检查domain时比较宽 \n
:param cookie: 要检查的cookie
:param driver: 被检查的driver
:return: 返回布尔值
"""
driver = driver or self.driver
for driver_cookie in driver.get_cookies():
if (cookie['name'] == driver_cookie['name'] and
@ -183,7 +216,11 @@ class Drission(object):
return False
def user_agent_to_session(self, driver: WebDriver = None, session: Session = None) -> None:
"""把driver的user-agent复制到session"""
"""把driver的user-agent复制到session \n
:param driver: 来源driver对象
:param session: 目标session对象
:return: None
"""
driver = driver or self.driver
session = session or self.session
selenium_user_agent = driver.execute_script("return navigator.userAgent;")

View File

@ -181,7 +181,7 @@ class DriverElement(DrissionElement):
"""返回当前元素下级符合条件的子元素,默认返回第一个 \n
示例 \n
- 用loc元组查找 \n
ele.ele((By.CLASS_NAME, 'ele_class')) - 返回所有class为ele_class的子元素 \n
ele.ele((By.CLASS_NAME, 'ele_class')) - 返回第一个class为ele_class的子元素 \n
- 用查询字符串查找 \n
查找方式属性tag name和属性文本xpathcss selector \n
其中@表示属性=表示精确匹配:表示模糊匹配无控制字符串时默认搜索该字符串 \n
@ -251,7 +251,7 @@ class DriverElement(DrissionElement):
:param show_errmsg: 出现异常时是否打印信息
:return: DriverElement对象组成的列表
"""
if not isinstance(loc_or_str, tuple) and not isinstance(loc_or_str, str):
if not isinstance(loc_or_str, (tuple, str)):
raise TypeError('Type of loc_or_str can only be tuple or str.')
return self.ele(loc_or_str, mode='all', show_errmsg=show_errmsg, timeout=timeout)
@ -405,7 +405,7 @@ class DriverElement(DrissionElement):
:return: 是否拖拽成功
"""
# x, y目标坐标点
if isinstance(ele_or_loc, DriverElement) or isinstance(ele_or_loc, WebElement):
if isinstance(ele_or_loc, (DriverElement, WebElement)):
target_x = ele_or_loc.location['x'] + ele_or_loc.size['width'] // 2
target_y = ele_or_loc.location['y'] + ele_or_loc.size['height'] // 2
elif isinstance(ele_or_loc, tuple):

View File

@ -19,7 +19,7 @@ def set_paths(driver_path: str = None,
user_data_path: str = None,
cache_path: str = None,
check_version: bool = True) -> None:
"""简易设置路径函数
"""快捷的路径设置函数 \n
:param driver_path: chromedriver.exe路径
:param chrome_path: chrome.exe路径
:param debugger_address: 调试浏览器地址127.0.0.1:9222
@ -57,10 +57,10 @@ def set_paths(driver_path: str = None,
def set_argument(arg: str, value: Union[bool, str]) -> None:
"""设置浏览器配置argument属性
"""设置浏览器配置argument属性 \n
:param arg: 属性名
:param value: 属性值有值的属性传入值没有的传入bool
:return:
:return: None
"""
do = DriverOptions()
do.remove_argument(arg)
@ -71,37 +71,59 @@ def set_argument(arg: str, value: Union[bool, str]) -> None:
def set_headless(on_off: bool = True) -> None:
"""设置headless"""
"""设置是否隐藏浏览器界面 \n
:param on_off: 开或关
:return: None
"""
set_argument('--headless', on_off)
def set_no_imgs(on_off: bool = True) -> None:
"""设置是否加载图片"""
"""设置是否禁止加载图片 \n
:param on_off: 开或关
:return: None
"""
set_argument('--blink-settings=imagesEnabled=false', on_off)
def set_no_js(on_off: bool = True) -> None:
"""设置禁用js"""
"""设置是否禁用js \n
:param on_off: 开或关
:return: None
"""
set_argument('--disable-javascript', on_off)
def set_mute(on_off: bool = True) -> None:
"""设置静音"""
"""设置是否静音 \n
:param on_off: 开或关
:return: None
"""
set_argument('--mute-audio', on_off)
def set_user_agent(user_agent: str) -> None:
"""设置user agent"""
"""设置user agent \n
:param user_agent: user agent文本
:return: None
"""
set_argument('user-agent', user_agent)
def set_proxy(proxy: str) -> None:
"""设置代理"""
"""设置代理 \n
:param proxy: 代理网址和端口
:return: None
"""
set_argument('--proxy-server', proxy)
def check_driver_version(driver_path: str = None, chrome_path: str = None) -> bool:
"""检查传入的chrome和chromedriver是否匹配"""
"""检查传入的chrome和chromedriver是否匹配 \n
:param driver_path: chromedriver.exe路径
:param chrome_path: chrome.exe路径
:return: 是否匹配
"""
print('正在检测可用性...')
om = OptionsManager()
driver_path = driver_path or om.get_value('paths', 'chromedriver_path') or 'chromedriver'

View File

@ -236,7 +236,7 @@ class MixPage(Null, SessionPage, DriverPage):
- 接收到元素对象时 \n
返回元素对象对象 \n
- 用loc元组查找 \n
ele.ele((By.CLASS_NAME, 'ele_class')) - 返回所有class为ele_class的子元素 \n
ele.ele((By.CLASS_NAME, 'ele_class')) - 返回第一个class为ele_class的子元素 \n
- 用查询字符串查找 \n
查找方式属性tag name和属性文本xpathcss selector \n
其中@表示属性=表示精确匹配:表示模糊匹配无控制字符串时默认搜索该字符串 \n

View File

@ -117,7 +117,7 @@ class SessionElement(DrissionElement):
"""返回当前元素下级符合条件的子元素,默认返回第一个 \n
示例 \n
- 用loc元组查找 \n
ele.ele((By.CLASS_NAME, 'ele_class')) - 返回所有class为ele_class的子元素 \n
ele.ele((By.CLASS_NAME, 'ele_class')) - 返回第一个class为ele_class的子元素 \n
- 用查询字符串查找 \n
查找方式属性tag name和属性文本xpathcss selector \n
其中@表示属性=表示精确匹配:表示模糊匹配无控制字符串时默认搜索该字符串 \n

View File

@ -133,7 +133,7 @@ class SessionPage(object):
:param show_errmsg: 出现异常时是否打印信息
:return: SessionElement对象组成的列表
"""
if not isinstance(loc_or_str, tuple) and not isinstance(loc_or_str, str):
if not isinstance(loc_or_str, (tuple, str)):
raise TypeError('Type of loc_or_str can only be tuple or str.')
return self.ele(loc_or_str, mode='all', show_errmsg=True)