mirror of
https://gitee.com/g1879/DrissionPage.git
synced 2024-12-10 04:00:23 +08:00
微调
This commit is contained in:
parent
063f85ea53
commit
5d4bec500b
@ -95,7 +95,7 @@ class OptionsManager(object):
|
|||||||
for j in items:
|
for j in items:
|
||||||
try:
|
try:
|
||||||
option[j[0]] = eval(self._conf.get(section, j[0]).replace('\\', '\\\\'))
|
option[j[0]] = eval(self._conf.get(section, j[0]).replace('\\', '\\\\'))
|
||||||
except:
|
except Exception:
|
||||||
option[j[0]] = self._conf.get(section, j[0])
|
option[j[0]] = self._conf.get(section, j[0])
|
||||||
|
|
||||||
return option
|
return option
|
||||||
|
@ -4,15 +4,16 @@
|
|||||||
@Contact : g1879@qq.com
|
@Contact : g1879@qq.com
|
||||||
@File : drission.py
|
@File : drission.py
|
||||||
"""
|
"""
|
||||||
|
from sys import exit
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
from requests import Session
|
from requests import Session
|
||||||
from requests.cookies import RequestsCookieJar
|
from requests.cookies import RequestsCookieJar
|
||||||
from selenium import webdriver
|
from selenium import webdriver
|
||||||
from selenium.common.exceptions import SessionNotCreatedException, WebDriverException
|
from selenium.common.exceptions import SessionNotCreatedException, WebDriverException
|
||||||
from selenium.webdriver.chrome.options import Options
|
from selenium.webdriver.chrome.options import Options
|
||||||
from selenium.webdriver.chrome.webdriver import WebDriver
|
from selenium.webdriver.chrome.webdriver import WebDriver
|
||||||
from sys import exit
|
|
||||||
from tldextract import extract
|
from tldextract import extract
|
||||||
from typing import Union
|
|
||||||
|
|
||||||
from .config import (_dict_to_chrome_options, _session_options_to_dict,
|
from .config import (_dict_to_chrome_options, _session_options_to_dict,
|
||||||
SessionOptions, DriverOptions, _chrome_options_to_dict, OptionsManager, _cookies_to_tuple)
|
SessionOptions, DriverOptions, _chrome_options_to_dict, OptionsManager, _cookies_to_tuple)
|
||||||
@ -116,7 +117,7 @@ class Drission(object):
|
|||||||
# 反反爬设置
|
# 反反爬设置
|
||||||
try:
|
try:
|
||||||
self._driver.execute_script('Object.defineProperty(navigator,"webdriver",{get:() => undefined,});')
|
self._driver.execute_script('Object.defineProperty(navigator,"webdriver",{get:() => undefined,});')
|
||||||
except:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# self._driver.execute_cdp_cmd(
|
# self._driver.execute_cdp_cmd(
|
||||||
@ -468,7 +469,7 @@ def _create_driver(chrome_path: str, driver_path: str, options: Options) -> WebD
|
|||||||
if driver_path:
|
if driver_path:
|
||||||
try:
|
try:
|
||||||
return webdriver.Chrome(driver_path, options=options)
|
return webdriver.Chrome(driver_path, options=options)
|
||||||
except:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# 当找不到 driver 且 chrome_path 为 None 时,说明安装的版本过高,改在系统路径中查找
|
# 当找不到 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
|
options.binary_location = chrome_path
|
||||||
try:
|
try:
|
||||||
return webdriver.Chrome(driver_path, options=options)
|
return webdriver.Chrome(driver_path, options=options)
|
||||||
except:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
print('无法启动,请检查浏览器路径,或手动设置chromedriver。\n下载地址:http://npm.taobao.org/mirrors/chromedriver/')
|
print('无法启动,请检查浏览器路径,或手动设置chromedriver。\n下载地址:http://npm.taobao.org/mirrors/chromedriver/')
|
||||||
|
@ -290,7 +290,7 @@ class DriverElement(DrissionElement):
|
|||||||
try:
|
try:
|
||||||
self.inner_ele.click()
|
self.inner_ele.click()
|
||||||
return True
|
return True
|
||||||
except:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# 若点击失败,用js方式点击
|
# 若点击失败,用js方式点击
|
||||||
@ -405,7 +405,7 @@ class DriverElement(DrissionElement):
|
|||||||
try:
|
try:
|
||||||
self.is_enabled()
|
self.is_enabled()
|
||||||
return True
|
return True
|
||||||
except:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def screenshot(self, path: str, filename: str = None) -> str:
|
def screenshot(self, path: str, filename: str = None) -> str:
|
||||||
@ -449,7 +449,7 @@ class DriverElement(DrissionElement):
|
|||||||
value = value.replace("'", "\\'")
|
value = value.replace("'", "\\'")
|
||||||
self.run_script(f"arguments[0].{prop}='{value}';")
|
self.run_script(f"arguments[0].{prop}='{value}';")
|
||||||
return True
|
return True
|
||||||
except:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def set_attr(self, attr: str, value: str) -> bool:
|
def set_attr(self, attr: str, value: str) -> bool:
|
||||||
@ -461,7 +461,7 @@ class DriverElement(DrissionElement):
|
|||||||
try:
|
try:
|
||||||
self.run_script(f"arguments[0].setAttribute(arguments[1], arguments[2]);", attr, value)
|
self.run_script(f"arguments[0].setAttribute(arguments[1], arguments[2]);", attr, value)
|
||||||
return True
|
return True
|
||||||
except:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def remove_attr(self, attr: str) -> bool:
|
def remove_attr(self, attr: str) -> bool:
|
||||||
@ -472,7 +472,7 @@ class DriverElement(DrissionElement):
|
|||||||
try:
|
try:
|
||||||
self.run_script(f'arguments[0].removeAttribute("{attr}");')
|
self.run_script(f'arguments[0].removeAttribute("{attr}");')
|
||||||
return True
|
return True
|
||||||
except:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def drag(self, x: int, y: int, speed: int = 40, shake: bool = True) -> bool:
|
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"。')
|
raise ValueError('para_type参数只能传入"text"、"value"或"index"。')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
elif isinstance(text_value_index, (list, tuple)):
|
elif isinstance(text_value_index, (list, tuple)):
|
||||||
@ -903,7 +903,7 @@ def _wait_ele(page_or_ele,
|
|||||||
if mode == 'del':
|
if mode == 'del':
|
||||||
try:
|
try:
|
||||||
loc_or_ele.is_enabled()
|
loc_or_ele.is_enabled()
|
||||||
except:
|
except Exception:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
elif mode == 'display' and loc_or_ele.is_displayed():
|
elif mode == 'display' and loc_or_ele.is_displayed():
|
||||||
@ -928,5 +928,5 @@ def _wait_ele(page_or_ele,
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
|
@ -87,7 +87,7 @@ class DriverPage(BasePage):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
self._driver.execute_script('Object.defineProperty(navigator,"webdriver",{get:() => undefined,});')
|
self._driver.execute_script('Object.defineProperty(navigator,"webdriver",{get:() => undefined,});')
|
||||||
except:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return self._url_available
|
return self._url_available
|
||||||
@ -225,7 +225,7 @@ class DriverPage(BasePage):
|
|||||||
"""返回标签页数量"""
|
"""返回标签页数量"""
|
||||||
try:
|
try:
|
||||||
return len(self.driver.window_handles)
|
return len(self.driver.window_handles)
|
||||||
except:
|
except Exception:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -278,7 +278,7 @@ class DriverPage(BasePage):
|
|||||||
self.driver.switch_to.new_window('tab')
|
self.driver.switch_to.new_window('tab')
|
||||||
if url:
|
if url:
|
||||||
self.get(url)
|
self.get(url)
|
||||||
except:
|
except Exception:
|
||||||
self.to_tab(-1)
|
self.to_tab(-1)
|
||||||
self.run_script(f'window.open("{url}");')
|
self.run_script(f'window.open("{url}");')
|
||||||
self.to_tab(-1)
|
self.to_tab(-1)
|
||||||
|
@ -323,7 +323,7 @@ def _get_chrome_version(path: str) -> Union[str, None]:
|
|||||||
try:
|
try:
|
||||||
return (popen(f'wmic datafile where "name=\'{path}\'" get version').read()
|
return (popen(f'wmic datafile where "name=\'{path}\'" get version').read()
|
||||||
.lower().split('\n')[2].replace(' ', ''))
|
.lower().split('\n')[2].replace(' ', ''))
|
||||||
except:
|
except Exception:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@ -402,7 +402,7 @@ class MixPage(SessionPage, DriverPage, BasePage):
|
|||||||
'download.default_directory']
|
'download.default_directory']
|
||||||
if not path:
|
if not path:
|
||||||
raise ValueError('未指定下载路径。')
|
raise ValueError('未指定下载路径。')
|
||||||
except:
|
except Exception:
|
||||||
raise IOError('无法找到下载路径。')
|
raise IOError('无法找到下载路径。')
|
||||||
|
|
||||||
return super().chrome_downloading(path)
|
return super().chrome_downloading(path)
|
||||||
|
@ -140,7 +140,7 @@ class ShadowRootElement(BaseElement):
|
|||||||
try:
|
try:
|
||||||
self.is_enabled()
|
self.is_enabled()
|
||||||
return True
|
return True
|
||||||
except:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# ----------------ShadowRootElement独有方法-----------------------
|
# ----------------ShadowRootElement独有方法-----------------------
|
||||||
|
323
docs/使用方法/获取元素信息.md
Normal file
323
docs/使用方法/获取元素信息.md
Normal 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>行元素</p>
|
||||||
|
<!--这是注释-->
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
```
|
||||||
|
|
||||||
|
## inner_html
|
||||||
|
|
||||||
|
此属性返回元素的 innerHTML 文本。
|
||||||
|
|
||||||
|
```python
|
||||||
|
inner_html = ele.inner_html
|
||||||
|
"""返回:
|
||||||
|
Hello World!
|
||||||
|
<p>行元素</p>
|
||||||
|
<!--这是注释-->
|
||||||
|
"""
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|
此属性返回元素所在的页面对象。
|
||||||
|
|
||||||
|
- 由页面对象生成的元素返回该页面对象,如 MixPage,DriverPage,SessionPage
|
||||||
|
- 由 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 始终返回 True,DriverElement 视乎元素是否还在 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 属性获取的是 outerHTML,ShadowRootElement 的 html 属性获取的是内部的。
|
||||||
|
|
||||||
|
## page
|
||||||
|
|
||||||
|
元素所在页面对象。
|
||||||
|
|
||||||
|
## inner_ele
|
||||||
|
|
||||||
|
从 js 中获取到的 shadow-root 元素。
|
||||||
|
|
||||||
|
## parent_ele
|
||||||
|
|
||||||
|
这是 ShadowRootElement 独有的属性,返回它所依附的普通元素对象。
|
||||||
|
|
||||||
|
## is_enabled()
|
||||||
|
|
||||||
|
与 DriverElement 一致。
|
||||||
|
|
||||||
|
## is_valid()
|
||||||
|
|
||||||
|
与 DriverElement 一致。
|
||||||
|
|
@ -22,7 +22,6 @@ element = page('some text')
|
|||||||
## 简单示例:
|
## 简单示例:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
<div id="one">
|
<div id="one">
|
||||||
@ -137,6 +136,8 @@ ele2 = ele1.prev # 获取 ele1 前面一个兄弟元素
|
|||||||
|
|
||||||
此属性返回当前元素的父元素。
|
此属性返回当前元素的父元素。
|
||||||
|
|
||||||
|
注:ShadowRootElement 的这个属性返回其所属元素。
|
||||||
|
|
||||||
```python
|
```python
|
||||||
ele2 = ele1.parent # 获取 ele1 的父元素
|
ele2 = ele1.parent # 获取 ele1 的父元素
|
||||||
```
|
```
|
||||||
|
Loading…
x
Reference in New Issue
Block a user