mirror of
https://gitee.com/g1879/DrissionPage.git
synced 2024-12-10 04:00:23 +08:00
修改ChromiumFrame,未完成;str_to_loc()修改tx=xxxx的语法,用text()替代.
This commit is contained in:
parent
6fedd57677
commit
51cb918b32
@ -1251,7 +1251,7 @@ def run_script(page_or_ele, script, as_expr=False, timeout=None, args=None, not_
|
|||||||
:param script: js文本
|
:param script: js文本
|
||||||
:param as_expr: 是否作为表达式运行,为True时args无效
|
:param as_expr: 是否作为表达式运行,为True时args无效
|
||||||
:param timeout: 超时时间
|
:param timeout: 超时时间
|
||||||
:param args: 参数,按顺序在js文本中对应argument[0]、argument[2]...
|
:param args: 参数,按顺序在js文本中对应argument[0]、argument[1]...
|
||||||
:param not_change: 执行时是否切换页面对象模式
|
:param not_change: 执行时是否切换页面对象模式
|
||||||
:return: js执行结果
|
:return: js执行结果
|
||||||
"""
|
"""
|
||||||
|
@ -13,6 +13,7 @@ from .chromium_element import ChromiumElement
|
|||||||
class ChromiumFrame(ChromiumBase):
|
class ChromiumFrame(ChromiumBase):
|
||||||
def __init__(self, page, ele):
|
def __init__(self, page, ele):
|
||||||
self.page = page
|
self.page = page
|
||||||
|
self.address = self.page.address
|
||||||
node = page.run_cdp('DOM.describeNode', nodeId=ele.node_id, not_change=True)['node']
|
node = page.run_cdp('DOM.describeNode', nodeId=ele.node_id, not_change=True)['node']
|
||||||
self.frame_id = node['frameId']
|
self.frame_id = node['frameId']
|
||||||
self._backend_id = ele.backend_id
|
self._backend_id = ele.backend_id
|
||||||
@ -42,20 +43,23 @@ class ChromiumFrame(ChromiumBase):
|
|||||||
attrs = [f"{attr}='{attrs[attr]}'" for attr in attrs]
|
attrs = [f"{attr}='{attrs[attr]}'" for attr in attrs]
|
||||||
return f'<ChromiumFrame {self.frame_ele.tag} {" ".join(attrs)}>'
|
return f'<ChromiumFrame {self.frame_ele.tag} {" ".join(attrs)}>'
|
||||||
|
|
||||||
# def _reload_document(self):
|
def _reload(self):
|
||||||
# self._frame_ele = ChromiumElement(self.page, backend_id=self._backend_id)
|
self._frame_ele = ChromiumElement(self.page, backend_id=self._backend_id)
|
||||||
# node = self.page.run_cdp('DOM.describeNode', nodeId=self._frame_ele.node_id, not_change=True)['node']
|
node = self.page.run_cdp('DOM.describeNode', nodeId=self._frame_ele.node_id, not_change=True)['node']
|
||||||
#
|
|
||||||
# if self._is_inner_frame():
|
if self._is_inner_frame():
|
||||||
# self._is_diff_domain = False
|
print('-111')
|
||||||
# self.doc_ele = ChromiumElement(self.page, backend_id=node['contentDocument']['backendNodeId'])
|
self._is_diff_domain = False
|
||||||
# super().__init__(self.page.address, self.page.tab_id, self.page.timeout)
|
self.doc_ele = ChromiumElement(self.page, backend_id=node['contentDocument']['backendNodeId'])
|
||||||
# else:
|
super().__init__(self.address, self.page.tab_id, self.page.timeout)
|
||||||
# self._is_diff_domain = True
|
print('+111')
|
||||||
# self._tab_obj.stop()
|
else:
|
||||||
# super().__init__(self.page.address, self.frame_id, self.page.timeout)
|
print('-222')
|
||||||
# obj_id = super().run_script('document;', as_expr=True)['objectId']
|
self._is_diff_domain = True
|
||||||
# self.doc_ele = ChromiumElement(self, obj_id=obj_id)
|
super().__init__(self.address, self.frame_id, self.page.timeout)
|
||||||
|
obj_id = super().run_script('document;', as_expr=True)['objectId']
|
||||||
|
self.doc_ele = ChromiumElement(self, obj_id=obj_id)
|
||||||
|
print('+222')
|
||||||
|
|
||||||
def _get_new_document(self):
|
def _get_new_document(self):
|
||||||
"""刷新cdp使用的document数据"""
|
"""刷新cdp使用的document数据"""
|
||||||
@ -156,7 +160,11 @@ class ChromiumFrame(ChromiumBase):
|
|||||||
@property
|
@property
|
||||||
def title(self):
|
def title(self):
|
||||||
"""返回页面title"""
|
"""返回页面title"""
|
||||||
return self.ele('t:title').text
|
while True:
|
||||||
|
try:
|
||||||
|
return self.ele('t:title').text
|
||||||
|
except:
|
||||||
|
self._reload()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def cookies(self):
|
def cookies(self):
|
||||||
@ -251,7 +259,7 @@ class ChromiumFrame(ChromiumBase):
|
|||||||
"""运行javascript代码 \n
|
"""运行javascript代码 \n
|
||||||
:param script: js文本
|
:param script: js文本
|
||||||
:param as_expr: 是否作为表达式运行,为True时args无效
|
:param as_expr: 是否作为表达式运行,为True时args无效
|
||||||
:param args: 参数,按顺序在js文本中对应argument[0]、argument[2]...
|
:param args: 参数,按顺序在js文本中对应argument[0]、argument[1]...
|
||||||
:return: 运行的结果
|
:return: 运行的结果
|
||||||
"""
|
"""
|
||||||
return self.doc_ele.run_script(script, as_expr=as_expr, *args)
|
return self.doc_ele.run_script(script, as_expr=as_expr, *args)
|
||||||
|
@ -28,6 +28,8 @@ class ChromiumFrame(ChromiumBase):
|
|||||||
|
|
||||||
def __repr__(self) -> str: ...
|
def __repr__(self) -> str: ...
|
||||||
|
|
||||||
|
def _reload(self) -> None: ...
|
||||||
|
|
||||||
def _get_new_document(self) -> None: ...
|
def _get_new_document(self) -> None: ...
|
||||||
|
|
||||||
def _onFrameAttached(self, **kwargs): ...
|
def _onFrameAttached(self, **kwargs): ...
|
||||||
|
@ -113,8 +113,8 @@ def get_loc(loc: Union[tuple, str], translate_css: bool = False) -> tuple:
|
|||||||
|
|
||||||
|
|
||||||
def str_to_loc(loc: str) -> tuple:
|
def str_to_loc(loc: str) -> tuple:
|
||||||
"""处理元素查找语句 \n
|
"""处理元素查找语句 \n
|
||||||
查找方式:属性、tag name及属性、文本、xpath、css selector、id、class \n
|
查找方式:属性、tag name及属性、文本、xpath、css selector、id、class \n
|
||||||
@表示属性,.表示class,#表示id,=表示精确匹配,:表示模糊匹配,无控制字符串时默认搜索该字符串 \n
|
@表示属性,.表示class,#表示id,=表示精确匹配,:表示模糊匹配,无控制字符串时默认搜索该字符串 \n
|
||||||
"""
|
"""
|
||||||
loc_by = 'xpath'
|
loc_by = 'xpath'
|
||||||
@ -159,7 +159,7 @@ def str_to_loc(loc: str) -> tuple:
|
|||||||
|
|
||||||
# 根据文本查找
|
# 根据文本查找
|
||||||
elif loc.startswith('text='):
|
elif loc.startswith('text='):
|
||||||
loc_str = f'//*[.={_make_search_str(loc[5:])}]'
|
loc_str = f'//*[text()={_make_search_str(loc[5:])}]'
|
||||||
elif loc.startswith('text:') and loc != 'text:':
|
elif loc.startswith('text:') and loc != 'text:':
|
||||||
loc_str = f'//*/text()[contains(., {_make_search_str(loc[5:])})]/..'
|
loc_str = f'//*/text()[contains(., {_make_search_str(loc[5:])})]/..'
|
||||||
|
|
||||||
|
@ -164,4 +164,79 @@ page.to_tab('0B300BEA6F1F1F4D5DE406872B79B1AD')
|
|||||||
|
|
||||||
## 📍 获取标签页对象
|
## 📍 获取标签页对象
|
||||||
|
|
||||||
# 未完待续
|
可以用`WebPage`或`ChromiumPage`的`get_tab()`方法获取标签页对象,然后可以使用这个对象对标签页进行操作。
|
||||||
|
|
||||||
|
`get_tab()`
|
||||||
|
|
||||||
|
**参数:**
|
||||||
|
|
||||||
|
- `tab_id`:要获取的标签页 id,为`None`时获取当前标签页
|
||||||
|
|
||||||
|
**返回:**`ChromiumTab`对象
|
||||||
|
|
||||||
|
```python
|
||||||
|
tab = page.get_tab() # 获取当前标签页对象
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📍 使用标签页对象
|
||||||
|
|
||||||
|
每个`ChromiumTab`对象控制一个浏览器标签页,方法和直接使用`ChromiumPage`一致,只比`ChromiumPage`少了控制标签页功能。
|
||||||
|
|
||||||
|
```python
|
||||||
|
tab.get('https://www.baidu.com') # 使用标签页对象
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📍 同时控制多标签页示例
|
||||||
|
|
||||||
|
下面的例子演示多个线程控制多个标签页进行内容采集。
|
||||||
|
|
||||||
|
```python
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
|
from DrissionPage import ChromiumPage
|
||||||
|
|
||||||
|
|
||||||
|
def 采集(tab):
|
||||||
|
# 采集 4 页
|
||||||
|
for _ in range(4):
|
||||||
|
# 获取某页所有库名称并打印
|
||||||
|
for i in tab.eles('.title project-namespace-path'):
|
||||||
|
print(i.text)
|
||||||
|
|
||||||
|
# 点击翻页
|
||||||
|
tab('@rel=next').click()
|
||||||
|
# 等待页面进入加载
|
||||||
|
tab.wait_loading()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# 新建页面对象
|
||||||
|
page = ChromiumPage()
|
||||||
|
# 第一个标签页访问网址
|
||||||
|
page.get('https://gitee.com/explore/ai')
|
||||||
|
# 获取第一个标签页对象
|
||||||
|
tab1 = page.get_tab()
|
||||||
|
# 新建一个标签页并访问另一个网址
|
||||||
|
page.new_tab('https://gitee.com/explore/machine-learning')
|
||||||
|
# 获取第二个标签页对象
|
||||||
|
tab2 = page.get_tab()
|
||||||
|
|
||||||
|
# 多线程同时处理多个页面
|
||||||
|
Thread(target=采集, args=(tab1,)).start()
|
||||||
|
Thread(target=采集, args=(tab2,)).start()
|
||||||
|
```
|
||||||
|
|
||||||
|
输出:
|
||||||
|
|
||||||
|
```console
|
||||||
|
MindSpore/mindspore
|
||||||
|
PaddlePaddle/Paddle
|
||||||
|
MindSpore/docs
|
||||||
|
scruel/Notes-ML-AndrewNg
|
||||||
|
MindSpore/graphengine
|
||||||
|
inspur-inna/inna1.0
|
||||||
|
MindSpore/course
|
||||||
|
MindSpore/community
|
||||||
|
|
||||||
|
后面省略。。。
|
||||||
|
```
|
||||||
|
258
docs/WebPage使用方法/3.9iframe操作.md
Normal file
258
docs/WebPage使用方法/3.9iframe操作.md
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
`<iframe>`元素是一种特殊的元素,它既是元素,也是页面,因此独立一个章节对其进行介绍。
|
||||||
|
|
||||||
|
与 selenium 不同,DrissionPage 无需切入切出即可处理`<iframe>`元素。因此可实现跨级元素查找、元素内部单独跳转、同时操作`<iframe>`内外元素、多线程控制多个`<iframe>`等操作,功能更灵活,逻辑更清晰。
|
||||||
|
|
||||||
|
我们使用菜鸟教程在线编辑器来演示:
|
||||||
|
|
||||||
|
[菜鸟教程在线编辑器 (runoob.com)](https://www.runoob.com/try/try.php?filename=tryhtml_iframe)
|
||||||
|
|
||||||
|
源代码框内容要作一点调整,然后按“点击运行”:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>菜鸟教程(runoob.com)</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<iframe id="sss" src="https://www.runoob.com">
|
||||||
|
<p>您的浏览器不支持 iframe 标签。</p>
|
||||||
|
</iframe>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
按`F12`,可以看到网页右侧是一个两层`<iframe>`,一个 id 是`'iframeResult'`的`<iframe>`里面有一个 id 是`'sss'`的`<iframe>`。最里层的`<iframe>`页面指向 https://www.runoob.com。
|
||||||
|
|
||||||
|
# ✔ 获取`<iframe>`对象
|
||||||
|
|
||||||
|
现在我们获取最里层`<iframe>`对象。方法和直接获取元素一样:
|
||||||
|
|
||||||
|
```python
|
||||||
|
iframe = page('#sss')
|
||||||
|
print(iframe.html)
|
||||||
|
```
|
||||||
|
|
||||||
|
输出:
|
||||||
|
|
||||||
|
```console
|
||||||
|
<iframe id="sss" src="https://www.runoob.com"><html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>菜鸟教程 - 学的不仅是技术,更是梦想!</title>
|
||||||
|
|
||||||
|
<meta name="robots" content="max-image-preview:large">
|
||||||
|
|
||||||
|
下面省略。。。
|
||||||
|
```
|
||||||
|
|
||||||
|
这个`ChromiumFrame`对象既是页面也是元素,下面演示其功能。
|
||||||
|
|
||||||
|
# ✔ 查找`<iframe>`内元素
|
||||||
|
|
||||||
|
从刚才获取元素对象看出,我们并不须要先切入 id 为`'iframeResult'`的`<iframe>`,就可以获取到里面的元素。所以我们获取元素也并不一定要先获取到`ChromiumFrame`对象。
|
||||||
|
|
||||||
|
## 📍 在`<iframe>`内查找
|
||||||
|
|
||||||
|
使用我们刚才获取到的元素,可以在里面查找元素:
|
||||||
|
|
||||||
|
```python
|
||||||
|
ele = iframe('首页')
|
||||||
|
print(ele)
|
||||||
|
|
||||||
|
# 输出:<ChromiumElement a href='https://www.runoob.com/' data-id='index' title='菜鸟教程' class='current'>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📍 页面跨`<iframe>`查找
|
||||||
|
|
||||||
|
如果`<iframe>`元素的网址和主页面是同域的,我们可以直接用页面对象查找`<iframe>`内部元素,而无需先获取`ChromiumFrame`对象:
|
||||||
|
|
||||||
|
```python
|
||||||
|
ele = page('首页')
|
||||||
|
print(ele)
|
||||||
|
|
||||||
|
# 输出:<ChromiumElement a href='https://www.runoob.com/' data-id='index' title='菜鸟教程' class='current'>
|
||||||
|
```
|
||||||
|
|
||||||
|
只要是同域名的,无论跨多少曾`<iframe>`都能用页面对象直接获取。
|
||||||
|
|
||||||
|
## 📍 与 selenium 对比
|
||||||
|
|
||||||
|
`WebPage`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from DrissionPage import WebPage
|
||||||
|
|
||||||
|
page = WebPage()
|
||||||
|
ele = page('首页')
|
||||||
|
```
|
||||||
|
|
||||||
|
`MixPage`(基于 selenium):
|
||||||
|
|
||||||
|
```python
|
||||||
|
from DrissionPage import MixPage
|
||||||
|
|
||||||
|
page = MixPage()
|
||||||
|
page.to_frame('#iframeResult')
|
||||||
|
page.to_frame('#sss')
|
||||||
|
ele = page('首页')
|
||||||
|
page.to_frame.main()
|
||||||
|
```
|
||||||
|
|
||||||
|
可见,原来的逻辑要切入切出,比较繁琐。
|
||||||
|
|
||||||
|
# ✔ `ChromiumFrame`的元素特征
|
||||||
|
|
||||||
|
正如上面所说,`ChromiumFrame`既是元素也是页面,这里说一下其元素方面的用法。
|
||||||
|
|
||||||
|
## 📍 `tab_id`
|
||||||
|
|
||||||
|
此属性返回`<iframe>`元素所在标签页的 id。
|
||||||
|
|
||||||
|
## 📍 `tag`
|
||||||
|
|
||||||
|
此属性返回元素名称。
|
||||||
|
|
||||||
|
## 📍 `html`
|
||||||
|
|
||||||
|
此属性返回整个`<iframe>`元素的 outerHTML 文本。
|
||||||
|
|
||||||
|
## 📍 `inner_html`
|
||||||
|
|
||||||
|
此属性返回 innerHTML 文本。
|
||||||
|
|
||||||
|
## 📍 `attrs`
|
||||||
|
|
||||||
|
此属性以`dict`形式返回元素所有 attribute 属性。
|
||||||
|
|
||||||
|
## 📍 `size`
|
||||||
|
|
||||||
|
此属性以`tuple`形式返回元素大小。
|
||||||
|
|
||||||
|
## 📍 `location`
|
||||||
|
|
||||||
|
此属性以`tuple`形式返回元素在主页面中的位置。
|
||||||
|
|
||||||
|
## 📍 `is_displayed`
|
||||||
|
|
||||||
|
此属性返回元素是否可见。
|
||||||
|
|
||||||
|
## 📍 `xpath`
|
||||||
|
|
||||||
|
此属性返回元素在其页面上的 xpath 路径。
|
||||||
|
|
||||||
|
## 📍 `css_path`
|
||||||
|
|
||||||
|
此属性返回元素在其页面上的 css selector 路径。
|
||||||
|
|
||||||
|
## 📍 `attr()`
|
||||||
|
|
||||||
|
此方法用于一个获取元素 attribute 属性。
|
||||||
|
|
||||||
|
**参数:**
|
||||||
|
|
||||||
|
- `attr`:属性名
|
||||||
|
|
||||||
|
**返回:** 属性值文本,没有该属性返回`None`
|
||||||
|
|
||||||
|
## 📍 `set_attr()`
|
||||||
|
|
||||||
|
此方法用于设置元素的 attribute 属性。
|
||||||
|
|
||||||
|
**参数:**
|
||||||
|
|
||||||
|
- `attr`:属性名
|
||||||
|
|
||||||
|
**返回:**`None`
|
||||||
|
|
||||||
|
## 📍 `remove_attr()`
|
||||||
|
|
||||||
|
此方法用于删除元素的 attribute 属性。
|
||||||
|
|
||||||
|
**参数:**
|
||||||
|
|
||||||
|
- `attr`:属性名
|
||||||
|
|
||||||
|
**返回:**`None`
|
||||||
|
|
||||||
|
## 📍 相对定位
|
||||||
|
|
||||||
|
相对定位方法与普通元素一致,详见获取元素章节。
|
||||||
|
|
||||||
|
- `parent()`:返回上面某一级父元素。
|
||||||
|
|
||||||
|
- `prev()`:返回前面的一个兄弟元素。
|
||||||
|
|
||||||
|
- `next()`:返回后面的一个兄弟元素。
|
||||||
|
|
||||||
|
- `before()`:返回当前元素前面的一个元素。
|
||||||
|
|
||||||
|
- `after()`:返回当前元素后面的一个元素。
|
||||||
|
|
||||||
|
- `prevs()`:返回前面全部兄弟元素或节点组成的列表。
|
||||||
|
|
||||||
|
- `nexts()`:返回后面全部兄弟元素或节点组成的列表。
|
||||||
|
|
||||||
|
- `befores()`:返回当前元素后面符合条件的全部兄弟元素或节点组成的列表。
|
||||||
|
|
||||||
|
# ✔ `ChromiumFrame`的页面特征
|
||||||
|
|
||||||
|
## 📍 `url`
|
||||||
|
|
||||||
|
此属性返回页面当前 url。
|
||||||
|
|
||||||
|
## 📍 `title`
|
||||||
|
|
||||||
|
此属性返回页面当前 title 文本。
|
||||||
|
|
||||||
|
## 📍 `cookies`
|
||||||
|
|
||||||
|
此属性返回页面当前 cookies 内容。
|
||||||
|
|
||||||
|
## 📍 `get()`
|
||||||
|
|
||||||
|
此方法用于实现`<iframe>`页面跳转。
|
||||||
|
|
||||||
|
```python
|
||||||
|
iframe.get('https://www.runoob.com/css3/css3-tutorial.html')
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📍 `refresh()`
|
||||||
|
|
||||||
|
此方法用于刷新页面。
|
||||||
|
|
||||||
|
```python
|
||||||
|
iframe.refresh()
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📍 `ready_state`
|
||||||
|
|
||||||
|
此属性为页面加载状态。
|
||||||
|
|
||||||
|
## 📍 `is_loading`
|
||||||
|
|
||||||
|
此属性返回页面是否正在加载。
|
||||||
|
|
||||||
|
## 📍 `active_ele`
|
||||||
|
|
||||||
|
此属性返回页面中焦点所在元素。
|
||||||
|
|
||||||
|
## 📍 `frame_size`
|
||||||
|
|
||||||
|
此属性以`tuple`形式返回页面大小。
|
||||||
|
|
||||||
|
## 📍 `run_script()`
|
||||||
|
|
||||||
|
此方法用于在`<iframe>`内执行 js 脚本。
|
||||||
|
|
||||||
|
**参数:**
|
||||||
|
|
||||||
|
- `script`:js文本
|
||||||
|
|
||||||
|
- `as_expr`:是否作为表达式运行,为`True`时`args`无效
|
||||||
|
|
||||||
|
- `*args`:参数,按顺序在 js 文本中对应 argument[0]、argument[1]...
|
||||||
|
|
||||||
|
**返回:** 运行的结果
|
@ -21,6 +21,7 @@
|
|||||||
* [🔨 3.6 获取网页信息](WebPage使用方法\3.6获取网页信息.md)
|
* [🔨 3.6 获取网页信息](WebPage使用方法\3.6获取网页信息.md)
|
||||||
* [🔨 3.7 页面操作](WebPage使用方法\3.7页面操作.md)
|
* [🔨 3.7 页面操作](WebPage使用方法\3.7页面操作.md)
|
||||||
* [🔨 3.8 标签页操作](WebPage使用方法\3.8标签页操作.md)
|
* [🔨 3.8 标签页操作](WebPage使用方法\3.8标签页操作.md)
|
||||||
|
* [🔨 3.9 iframe操作](WebPage使用方法\3.9iframe操作.md)
|
||||||
|
|
||||||
* [🛠 4 MixPage 使用方法](#)
|
* [🛠 4 MixPage 使用方法](#)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user