This commit is contained in:
g1879 2021-12-14 17:37:17 +08:00
parent 063f85ea53
commit 5d4bec500b
9 changed files with 346 additions and 21 deletions

View File

@ -95,7 +95,7 @@ class OptionsManager(object):
for j in items:
try:
option[j[0]] = eval(self._conf.get(section, j[0]).replace('\\', '\\\\'))
except:
except Exception:
option[j[0]] = self._conf.get(section, j[0])
return option

View File

@ -4,15 +4,16 @@
@Contact : g1879@qq.com
@File : drission.py
"""
from sys import exit
from typing import Union
from requests import Session
from requests.cookies import RequestsCookieJar
from selenium import webdriver
from selenium.common.exceptions import SessionNotCreatedException, WebDriverException
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.webdriver import WebDriver
from sys import exit
from tldextract import extract
from typing import Union
from .config import (_dict_to_chrome_options, _session_options_to_dict,
SessionOptions, DriverOptions, _chrome_options_to_dict, OptionsManager, _cookies_to_tuple)
@ -116,7 +117,7 @@ class Drission(object):
# 反反爬设置
try:
self._driver.execute_script('Object.defineProperty(navigator,"webdriver",{get:() => undefined,});')
except:
except Exception:
pass
# self._driver.execute_cdp_cmd(
@ -468,7 +469,7 @@ def _create_driver(chrome_path: str, driver_path: str, options: Options) -> WebD
if driver_path:
try:
return webdriver.Chrome(driver_path, options=options)
except:
except Exception:
pass
# 当找不到 driver 且 chrome_path 为 None 时,说明安装的版本过高,改在系统路径中查找
@ -481,7 +482,7 @@ def _create_driver(chrome_path: str, driver_path: str, options: Options) -> WebD
options.binary_location = chrome_path
try:
return webdriver.Chrome(driver_path, options=options)
except:
except Exception:
pass
print('无法启动请检查浏览器路径或手动设置chromedriver。\n下载地址http://npm.taobao.org/mirrors/chromedriver/')

View File

@ -290,7 +290,7 @@ class DriverElement(DrissionElement):
try:
self.inner_ele.click()
return True
except:
except Exception:
pass
# 若点击失败用js方式点击
@ -405,7 +405,7 @@ class DriverElement(DrissionElement):
try:
self.is_enabled()
return True
except:
except Exception:
return False
def screenshot(self, path: str, filename: str = None) -> str:
@ -449,7 +449,7 @@ class DriverElement(DrissionElement):
value = value.replace("'", "\\'")
self.run_script(f"arguments[0].{prop}='{value}';")
return True
except:
except Exception:
return False
def set_attr(self, attr: str, value: str) -> bool:
@ -461,7 +461,7 @@ class DriverElement(DrissionElement):
try:
self.run_script(f"arguments[0].setAttribute(arguments[1], arguments[2]);", attr, value)
return True
except:
except Exception:
return False
def remove_attr(self, attr: str) -> bool:
@ -472,7 +472,7 @@ class DriverElement(DrissionElement):
try:
self.run_script(f'arguments[0].removeAttribute("{attr}");')
return True
except:
except Exception:
return False
def drag(self, x: int, y: int, speed: int = 40, shake: bool = True) -> bool:
@ -790,7 +790,7 @@ class Select(object):
raise ValueError('para_type参数只能传入"text""value""index"')
return True
except:
except Exception:
return False
elif isinstance(text_value_index, (list, tuple)):
@ -903,7 +903,7 @@ def _wait_ele(page_or_ele,
if mode == 'del':
try:
loc_or_ele.is_enabled()
except:
except Exception:
return True
elif mode == 'display' and loc_or_ele.is_displayed():
@ -928,5 +928,5 @@ def _wait_ele(page_or_ele,
return True
except:
except Exception:
return False

View File

@ -87,7 +87,7 @@ class DriverPage(BasePage):
try:
self._driver.execute_script('Object.defineProperty(navigator,"webdriver",{get:() => undefined,});')
except:
except Exception:
pass
return self._url_available
@ -225,7 +225,7 @@ class DriverPage(BasePage):
"""返回标签页数量"""
try:
return len(self.driver.window_handles)
except:
except Exception:
return 0
@property
@ -278,7 +278,7 @@ class DriverPage(BasePage):
self.driver.switch_to.new_window('tab')
if url:
self.get(url)
except:
except Exception:
self.to_tab(-1)
self.run_script(f'window.open("{url}");')
self.to_tab(-1)

View File

@ -323,7 +323,7 @@ def _get_chrome_version(path: str) -> Union[str, None]:
try:
return (popen(f'wmic datafile where "name=\'{path}\'" get version').read()
.lower().split('\n')[2].replace(' ', ''))
except:
except Exception:
return None

View File

@ -402,7 +402,7 @@ class MixPage(SessionPage, DriverPage, BasePage):
'download.default_directory']
if not path:
raise ValueError('未指定下载路径。')
except:
except Exception:
raise IOError('无法找到下载路径。')
return super().chrome_downloading(path)

View File

@ -140,7 +140,7 @@ class ShadowRootElement(BaseElement):
try:
self.is_enabled()
return True
except:
except Exception:
return False
# ----------------ShadowRootElement独有方法-----------------------

View File

@ -0,0 +1,323 @@
# 获取元素信息
获取到须要的页面元素后,可以使用元素对象获取元素的信息。
本库有三种元素对象,分别是 DriverElement、ShadowRootElement、SessionElement前两者是 d 模式下通过浏览器页面元素生成后者由静态文本生成。DriverElement 和
SessionElement 的基本属性一致。
ShadowRootElement 由于是 shadow dom 元素,属性比较其余两种少,下文单独介绍。
## 实际示例:
```python
from DrissionPage import MixPage
page = MixPage('s')
page.get('https://gitee.com/explore')
# 获取推荐目录下所有 a 元素
li_eles = page('tag:ul@@text():全部推荐项目').eles('t:a')
for i in li_eles: # 遍历列表
print(i.tag, i.text, i.attr('href')) # 获取并打印标签名、文本、href 属性
"""输出:
a 全部推荐项目 https://gitee.com/explore/all
a 前沿技术 https://gitee.com/explore/new-tech
a 智能硬件 https://gitee.com/explore/hardware
a IOT/物联网/边缘计算 https://gitee.com/explore/iot
a 车载应用 https://gitee.com/explore/vehicle
以下省略……
"""
```
# 基本属性
假设 ele 为以下 div 元素的对象:
```html
<div id="div1">Hello World!
<p>行元素</p>
<!--这是注释-->
</div>
```
## html
此属性返回元素的 outerHTML 文本。
```python
html = ele.html
"""返回:
<div id="div1">Hello World!
<p>&#34892;&#20803;&#32032;</p>
<!--&#36825;&#26159;&#27880;&#37322;-->
</div>
"""
```
## inner_html
此属性返回元素的 innerHTML 文本。
```python
inner_html = ele.inner_html
"""返回:
Hello World!
<p>&#34892;&#20803;&#32032;</p>
<!--&#36825;&#26159;&#27880;&#37322;-->
"""
```
## tag
此属性返回元素的标签名。
```python
tag = ele.tag
# 返回div
```
## text
此属性返回元素内所有文本组合成的字符串。
该字符串已格式化,即已转码,已去除多余换行符,符合人读取习惯,便于直接使用。无须重复写处理代码。
```python
text = ele.text
"""返回:
Hello World!
行元素
"""
```
## raw_text
此属性返回元素内原始文本。
```python
text = ele.raw_text
"""返回(注意保留了元素间的空格和换行):
Hello World!
行元素
"""
```
## texts()
此方法返回元素内所有直接子节点的文本,包括元素和文本节点。 它有一个参数 text_node_only为True 时则只获取只返回文本节点。这个方法适用于获取文本节点和元素节点混排的情况。
```python
texts = ele.texts()
print(e.texts(text_node_only=True))
# 输出:['Hello World!', '行元素']
print(e.texts())
# 输出:['Hello World!']
```
## comments
```python
comments = ele.comments
# 返回:[<!--这是注释-->]
```
## attrs
此属性以字典形式返回元素所有属性及值。
```python
attrs = ele.attrs
# 返回:{'id': 'div1'}
```
## attr()
此方法返回元素某个 attribute 属性值。它接收一个字符串参数 attr返回该属性值文本无该属性时返回 None。
此属性返回的 src、href 属性为已补充完整的路径。text 属性为已格式化文本innerText 属性为未格式化文本,
```python
ele_id = ele.attr('id')
# 返回div1
```
## link
此方法返回元素的 href 属性或 src 属性,没有这两个属性则返回 None。
```html
<a href='http://www.baidu.com'>百度</a>
```
假设 a_ele 为以上元素的对象:
```python
link = a_ele.link
# 返回http://www.baidu.com
```
## page
此属性返回元素所在的页面对象。
- 由页面对象生成的元素返回该页面对象,如 MixPageDriverPageSessionPage
- 由 html 文本直接生成的 SessionElement 的 page 属性为 None。
```python
page = ele.page
```
## inner_ele
此属性返回被当前元素包装的对应模式原本的元素对象。
d 模式包装的是一个 selenium 的 WebElement 对象s 模式包装的是一个 lxml 的 HtmlElement 对象。
获取该对象,可直接使用该对象以该库的原生代码来执行须要的操作,便于不同项目的对接,及使用本库没有封装的功能。
```python
web_ele = ele.inner_ele
web_ele.find_element(By.ID, 'ele_id').click() # 使用 selenium 原生的元素点击方法
```
## xpath
此属性返回当前元素在页面中 xpath 的绝对路径。
```python
xpath = ele.xpath # 返回:/html/body/div
```
## css_path
此属性返回当前元素在页面中 css selector 的绝对路径。
```python
css = ele.css_path # 返回::nth-child(1)>:nth-child(1)>:nth-child(1)
```
## is_valid()
此方法返回当前元素是否可用。SessionElement 始终返回 TrueDriverElement 视乎元素是否还在 DOM 内返回布尔值。
```python
is_valid = ele.is_valid()
```
# DriverElement 独有属性
## size
此属性以字典形式返回元素的大小。
```python
size = ele.size
# 返回:{'height': 50, 'width': 50}
```
## location
此属性以字典形式返回元素坐标。
```python
loc = ele.location
# 返回:{'x': 50, 'y': 50}
```
## before
此属性以文本形式返回当前元素的 ::before 伪元素内容。
```python
before_txt = ele.before
```
## after
此属性以文本形式返回当前元素的 ::after 伪元素内容。
```python
after_txt = ele.after
```
## get_style_property()
该方法返回元素 css 样式属性值可获取伪元素的属性。它有两个参数style 参数输入样式属性名称pseudo_ele 参数输入伪元素名称,省略则获取普通元素的 css 样式属性。
```python
prop = ele.get_style_property('color', 'first-letter')
```
## prop()
此方法返回 property 属性值。它接收一个字符串参数,返回该参数的属性值。
```python
prop = ele.peop('value')
```
## select
此属性返回 select 元素用于处理下拉列表的 Select 类(下一节说明),非下拉列表元素返回 False。
```python
select = ele.select
```
## is_selected()
此方法以布尔值返回元素是否选中。
```python
selected = ele.is_selected()
```
## is_enabled()
此方法以布尔值返回元素是否可用。
```python
enable = ele.is_enabled()
```
## is_displayed()
此方法以布尔值返回元素是否可见。
```python
displayed = ele.is_displayed()
```
# ShadowRootElement 属性
本库把 shadow dom 的 root 看作一个元素处理,可以获取属性,也可以执行其下级的查找,但其属性比较少。有如下这些:
## tag
元素标签名
## html
shadow-root 内的 html 文本,与其余两种元素不一样,其余两种的 html 属性获取的是 outerHTMLShadowRootElement 的 html 属性获取的是内部的。
## page
元素所在页面对象。
## inner_ele
从 js 中获取到的 shadow-root 元素。
## parent_ele
这是 ShadowRootElement 独有的属性,返回它所依附的普通元素对象。
## is_enabled()
与 DriverElement 一致。
## is_valid()
与 DriverElement 一致。

View File

@ -22,7 +22,6 @@ element = page('some text')
## 简单示例:
```html
<html>
<body>
<div id="one">
@ -137,6 +136,8 @@ ele2 = ele1.prev # 获取 ele1 前面一个兄弟元素
此属性返回当前元素的父元素。
ShadowRootElement 的这个属性返回其所属元素。
```python
ele2 = ele1.parent # 获取 ele1 的父元素
```