diff --git a/DrissionPage/config.py b/DrissionPage/config.py
index db07e88..2f3a737 100644
--- a/DrissionPage/config.py
+++ b/DrissionPage/config.py
@@ -483,6 +483,9 @@ class DriverOptions(Options):
self.timeouts['pageLoad'] *= 1000
self.timeouts['script'] *= 1000
+ if '--no-sandbox' not in self._arguments:
+ self._arguments.append('--no-sandbox')
+
@property
def driver_path(self) -> str:
"""chromedriver文件路径"""
diff --git a/DrissionPage/drission.py b/DrissionPage/drission.py
index 7aaae69..3bb12ca 100644
--- a/DrissionPage/drission.py
+++ b/DrissionPage/drission.py
@@ -118,6 +118,11 @@ class Drission(object):
# -----------创建WebDriver对象-----------
self._driver = _create_driver(chrome_path, driver_path, self.driver_options)
+ # -----------解决接管新版浏览器不能定位到正确的标签页的问题-----------
+ active_tab = self._driver.window_handles[0]
+ if active_tab != self._driver.current_window_handle:
+ self._driver.switch_to.window(active_tab)
+
# 反反爬设置
try:
self._driver.execute_script('Object.defineProperty(navigator,"webdriver",{get:() => undefined,});')
@@ -448,7 +453,7 @@ def _create_chrome(chrome_path: str, port: str, args: list, proxy: dict) -> tupl
# ----------创建浏览器进程----------
try:
- debugger = Popen(f'{chrome_path} --remote-debugging-port={port} {args}', shell=False)
+ debugger = Popen(f'"{chrome_path}" --remote-debugging-port={port} {args}', shell=False)
if chrome_path == 'chrome.exe':
from .common import get_exe_path_from_port
diff --git a/DrissionPage/driver_element.py b/DrissionPage/driver_element.py
index c312fa6..683dd65 100644
--- a/DrissionPage/driver_element.py
+++ b/DrissionPage/driver_element.py
@@ -764,10 +764,7 @@ class DriverElement(DrissionElement):
:param loc: 筛选条件,可用selenium的(By, str),也可用本库定位语法
:return: DriverElement对象
"""
- try:
- from selenium.webdriver.support.relative_locator import RelativeBy
- except ImportError:
- raise ImportError('该方法只支持selenium4及以上版本。')
+ from selenium.webdriver.support.relative_locator import RelativeBy
if isinstance(loc, str):
loc = str_to_loc(loc)
diff --git a/DrissionPage/driver_page.py b/DrissionPage/driver_page.py
index 8f2f46d..854952c 100644
--- a/DrissionPage/driver_page.py
+++ b/DrissionPage/driver_page.py
@@ -334,15 +334,9 @@ class DriverPage(BasePage):
:param url: 新标签页跳转到的网址
:return: None
"""
- try: # selenium4新增功能,须配合新版浏览器
- self.driver.switch_to.new_window('tab')
- if url:
- self.get(url)
-
- except Exception:
- self.to_tab(-1)
- self.run_script(f'window.open("{url}");')
- self.to_tab(-1)
+ self.driver.switch_to.new_window('tab')
+ if url:
+ self.get(url)
def close_tabs(self, num_or_handles: Union[int, str, list, tuple] = None) -> None:
"""关闭传入的标签页,默认关闭当前页。可传入多个 \n
diff --git a/docs/使用方法/下载文件.md b/docs/使用方法/下载文件.md
index d2b9386..b83fa8a 100644
--- a/docs/使用方法/下载文件.md
+++ b/docs/使用方法/下载文件.md
@@ -1,219 +1,220 @@
-selenium 缺乏对浏览器下载文件的有效管理,难以进行检测下载状态、重命名、失败管理。
-使用 requests 下载文件能较好实现以上功能,但代码较为繁琐。
-因此 DrissionPage 提供了高效可靠的下载工具,整合了两者优点,可从 selenium 获取登录信息,用 requests 进行下载。弥补了 selenium 的不足,使下载简洁高效。
-
-?> 为了增强灵活性,该工具现在独立打包成一个库,叫 DownloadKit,详细用法见:[DownloadKit](https://gitee.com/g1879/DownloadKit)
-
-# 功能
-
-- 支持多线程同时下载多个文件
-- 大文件自动分块使用多线程下载
-- 自动任务调度,简易的任务添加方式
-- 支持 d 模式下用 requests 下载文件
-- 自动创建目标路径
-- 自动去除路径中的非法字符
-- 下载时支持文件重命名
-- 自动处理文件名冲突
-- 显示下载进度
-- 支持 post 方式
-- 支持自定义连接参数
-- 任务失败自动重试
-
-# 单线程下载方式
-
-`MixPage`对象的`download`属性是一个`DownloadKit`对象,为尽量与旧版兼容,该属性可直接调用。如`page.download(url, save_path)`
-?> 使用这个方式时效果与旧版一致,下载一个文件时会阻塞程序,因此更加建议用后文讲述的多线程方法。
-
-参数:
-
-- file_ur:文件 url
-- goal_path:存放路径,填写到文件夹,不填写文件名
-- rename:重命名文件,可不写扩展名,不输入则用网络文件原名
-- file_exists:若存在同名文件,可选择`'rename'`,`'overwrite'`,`'skip'`方式处理,若选择重命名,会在文件名后面添加序号
-- post_data:post 方式的数据,这个参数不为`None`时自动转成 post 方式
-- show_msg:是否显示下载信息和进度
-- **kwargs:连接参数,与 requests 的一致
-
-返回:下载是否成功和状态信息的元组。
-
-```python
-from DrissionPage import MixPage
-
-page = MixPage()
-# 文件 url
-url = 'https://www.baidu.com/img/flexible/logo/pc/result.png'
-# 存放路径
-save_path = r'C:\download'
-
-# 重命名为img.png,存在重名时自动在文件名末尾加上序号,显示下载进度
-res = page.download(url, save_path, 'img', 'rename', show_msg=True)
-# 打印结果
-print(res)
-```
-
-显示:
-
-```shell
-url:https://www.baidu.com/img/flexible/logo/pc/result.png
-文件名:img.png
-目标路径:C:\download
-100% 下载完成 C:\download\img.png
-
-(True, 'C:\\download\\img.png')
-```
-
-# 多线程并发下载方式
-
-你可以往`DownloadKit`对象添加个数不限的下载任务,它会自动调配线程去完成这些任务。
-默认为 10 个线程。
-
-## 添加任务
-
-使用`add()`方法添加任务
-
-参数:
-
-- file_ur:文件 url
-- goal_path:存放路径,填写到文件夹,不填写文件名
-- session:可指定使用的`Session`对象,默认使用`MixPage`内置的`Session`对象
-- rename:重命名文件,可不写扩展名,不输入则用网络文件原名
-- file_exists:若存在同名文件,可选择`'rename'`,`'overwrite'`,`'skip'`方式处理,若选择重命名,会在文件名后面添加序号
-- post_data:post 方式的数据,这个参数不为`None`时自动转成 post 方式
-- **kwargs:连接参数,与 requests 的一致
-
-返回:任务对象,可通过任务对象查看任务状态和结果
-
-```python
-from DrissionPage import MixPage
-
-page = MixPage('s')
-# 文件 url
-url = 'https://www.baidu.com/img/flexible/logo/pc/result.png'
-# 存放路径
-save_path = r'C:\download'
-
-# 返回一个任务对象
-mission = page.download.add(url, save_path)
-
-# 通过任务对象查看状态
-print(mission.rate, mission.info)
-```
-
-输出:
-
-```shell
-90% '下载中'
-```
-
-## 实时查看所有线程进度
-
-多线程方式不会实时显示下载进度,可用`show()`方法把下载进度打印出来。
-
-!> **注意:**
若使用 pyCharm 运行,须在运行配置里勾选“模拟输出控制台中的终端”才能正常显示输出。
-
-参数:
-
-- asyn:是否异步进行
-- keep:任务全部完成后是否保持显示
-
-返回:None
-
-```python
-url = 'https://example.com/file/abc.zip'
-mission = page.download.add(url, r'.\files')
-page.download.show()
-```
-
-输出:
-
-```shell
-等待任务数:0
-线程0:97.41% D:\files\abc.zip
-线程1:空闲
-线程2:空闲
-.....
-```
-
-?> **Tips:**
`keep`参数为`True`时,即使所有任务都已结束仍会一直打印进度,可以按`enter`结束。
-
-## 等待任务结束
-
-有时须要等待任务结束,以便获取结果,可用`wait()`方法。 当传入任务时,等待该任务结束并返回结果。不传入参数时等待所有任务结束,与`show()`方法一致。
-
-参数:
-
-- mission:任务对象或任务`id`,为`None`时等待所有任务结束
-- show:是否显示进度
-
-返回:
-
-- 指定任务时,返回任务结果和信息组成的两位 tuple。`True`表示成功,`False`表示失败,`None`表示跳过。
-- 不指定任务时,返回`None`
-
-!> **注意:**
若使用 pyCharm 运行,须在运行配置里勾选“模拟输出控制台中的终端”才能正常显示输出。
-
-```python
-url = 'https://www.baidu.com/img/PCfb_5bf082d29588c07f842ccde3f97243ea.png'
-mission = page.download.add(url, save_path)
-page.download.wait(mission)
-```
-
-输出:
-
-```shell
-url:https://www.baidu.com/img/PCfb_5bf082d29588c07f842ccde3f97243ea.png
-文件名:PCfb_5bf082d29588c07f842ccde3f97243ea_4.png
-目标路径:D:\files
-100% 下载完成 D:\files\PCfb_5bf082d29588c07f842ccde3f97243ea_4.png
-```
-
-## 获取某个任务结果
-
-从`add()`方法返回的`Mission`对象,可查看该任务执行情况。
-
-`Mission`对象属性:
-
-- id:任务 id
-- file_name:要保存的文件名
-- path:要保存的路径
-- data:任务数据
-- state:任务状态,有`'waiting'`、`'running'`、`'done'`三种
-- rate:任务进度,以百分比显示
-- info:任务信息,成功会返回文件绝对路径,失败会显示原因
-- result:任务结果,`True`表示成功,`False`表示失败,`None`表示跳过
-
-```python
-mission = page.download.add(url)
-print(mission.state)
-```
-
-输出:
-
-```python
-running
-```
-
-## 下载设置
-
-可使用以下属性进行配置:
-
-```python
-# 设置线程数,只能在没有任务在运行的时候进行
-page.download.roads = 20
-
-# 大文件分块大小,默认 20MB
page.downloadd.block_size = '50M'
-
-# 设置保存路径,设置后每个任务会使用这个路径,也可添加任务时单独设置
-page.download.goal_path = r'D:\tmp'
-
-# 设置重试次数,初始为继承 page 的 retry_times 属性
-page.download.retry = 5
-
-# 设置失败重试间隔,初始为继承 page 的 retry_interval 属性
-page.download.interval = 2
-
-# 设置存在文件名冲突时的处理方式,可选 'skip', 'overwrite', 'rename'
-page.download.file_exists = 'skip'
-```
-
-?> **Tips:**
重试次数和间隔在初始化时继承页面对象的`retry_times`和`retry_interval`属性,可用上面例子的方法对下载的重试次数和间隔进行设置,设置后不会影响页面对象的设置。
+selenium 缺乏对浏览器下载文件的有效管理,难以进行检测下载状态、重命名、失败管理。
+使用 requests 下载文件能较好实现以上功能,但代码较为繁琐。
+因此 DrissionPage 提供了高效可靠的下载工具,整合了两者优点,可从 selenium 获取登录信息,用 requests 进行下载。弥补了 selenium 的不足,使下载简洁高效。
+
+?> 为了增强灵活性,该工具现在独立打包成一个库,叫 DownloadKit,详细用法见:[DownloadKit](https://gitee.com/g1879/DownloadKit)
+
+# 功能
+
+- 支持多线程同时下载多个文件
+- 大文件自动分块使用多线程下载
+- 自动任务调度,简易的任务添加方式
+- 支持 d 模式下用 requests 下载文件
+- 自动创建目标路径
+- 自动去除路径中的非法字符
+- 下载时支持文件重命名
+- 自动处理文件名冲突
+- 显示下载进度
+- 支持 post 方式
+- 支持自定义连接参数
+- 任务失败自动重试
+
+# 单线程下载方式
+
+`MixPage`对象的`download`属性是一个`DownloadKit`对象,为尽量与旧版兼容,该属性可直接调用。如`page.download(url, save_path)`
+?> 使用这个方式时效果与旧版一致,下载一个文件时会阻塞程序,因此更加建议用后文讲述的多线程方法。
+
+参数:
+
+- file_ur:文件 url
+- goal_path:存放路径,填写到文件夹,不填写文件名
+- rename:重命名文件,可不写扩展名,不输入则用网络文件原名
+- file_exists:若存在同名文件,可选择`'rename'`,`'overwrite'`,`'skip'`方式处理,若选择重命名,会在文件名后面添加序号
+- post_data:post 方式的数据,这个参数不为`None`时自动转成 post 方式
+- show_msg:是否显示下载信息和进度
+- **kwargs:连接参数,与 requests 的一致
+
+返回:下载是否成功和状态信息的元组。
+
+```python
+from DrissionPage import MixPage
+
+page = MixPage()
+# 文件 url
+url = 'https://www.baidu.com/img/flexible/logo/pc/result.png'
+# 存放路径
+save_path = r'C:\download'
+
+# 重命名为img.png,存在重名时自动在文件名末尾加上序号,显示下载进度
+res = page.download(url, save_path, 'img', 'rename', show_msg=True)
+# 打印结果
+print(res)
+```
+
+显示:
+
+```shell
+url:https://www.baidu.com/img/flexible/logo/pc/result.png
+文件名:img.png
+目标路径:C:\download
+100% 下载完成 C:\download\img.png
+
+(True, 'C:\\download\\img.png')
+```
+
+# 多线程并发下载方式
+
+你可以往`DownloadKit`对象添加个数不限的下载任务,它会自动调配线程去完成这些任务。
+默认为 10 个线程。
+
+## 添加任务
+
+使用`add()`方法添加任务
+
+参数:
+
+- file_ur:文件 url
+- goal_path:存放路径,填写到文件夹,不填写文件名
+- session:可指定使用的`Session`对象,默认使用`MixPage`内置的`Session`对象
+- rename:重命名文件,可不写扩展名,不输入则用网络文件原名
+- file_exists:若存在同名文件,可选择`'rename'`,`'overwrite'`,`'skip'`方式处理,若选择重命名,会在文件名后面添加序号
+- post_data:post 方式的数据,这个参数不为`None`时自动转成 post 方式
+- **kwargs:连接参数,与 requests 的一致
+
+返回:任务对象,可通过任务对象查看任务状态和结果
+
+```python
+from DrissionPage import MixPage
+
+page = MixPage('s')
+# 文件 url
+url = 'https://www.baidu.com/img/flexible/logo/pc/result.png'
+# 存放路径
+save_path = r'C:\download'
+
+# 返回一个任务对象
+mission = page.download.add(url, save_path)
+
+# 通过任务对象查看状态
+print(mission.rate, mission.info)
+```
+
+输出:
+
+```shell
+90% '下载中'
+```
+
+## 实时查看所有线程进度
+
+多线程方式不会实时显示下载进度,可用`show()`方法把下载进度打印出来。
+
+!> **注意:**
若使用 pyCharm 运行,须在运行配置里勾选“模拟输出控制台中的终端”才能正常显示输出。
+
+参数:
+
+- asyn:是否异步进行
+- keep:任务全部完成后是否保持显示
+
+返回:None
+
+```python
+url = 'https://example.com/file/abc.zip'
+mission = page.download.add(url, r'.\files')
+page.download.show()
+```
+
+输出:
+
+```shell
+等待任务数:0
+线程0:97.41% D:\files\abc.zip
+线程1:空闲
+线程2:空闲
+.....
+```
+
+?> **Tips:**
`keep`参数为`True`时,即使所有任务都已结束仍会一直打印进度,可以按`enter`结束。
+
+## 等待任务结束
+
+有时须要等待任务结束,以便获取结果,可用`wait()`方法。 当传入任务时,等待该任务结束并返回结果。不传入参数时等待所有任务结束,与`show()`方法一致。
+
+参数:
+
+- mission:任务对象或任务`id`,为`None`时等待所有任务结束
+- show:是否显示进度
+
+返回:
+
+- 指定任务时,返回任务结果和信息组成的两位 tuple。`True`表示成功,`False`表示失败,`None`表示跳过。
+- 不指定任务时,返回`None`
+
+!> **注意:**
若使用 pyCharm 运行,须在运行配置里勾选“模拟输出控制台中的终端”才能正常显示输出。
+
+```python
+url = 'https://www.baidu.com/img/PCfb_5bf082d29588c07f842ccde3f97243ea.png'
+mission = page.download.add(url, save_path)
+page.download.wait(mission)
+```
+
+输出:
+
+```shell
+url:https://www.baidu.com/img/PCfb_5bf082d29588c07f842ccde3f97243ea.png
+文件名:PCfb_5bf082d29588c07f842ccde3f97243ea_4.png
+目标路径:D:\files
+100% 下载完成 D:\files\PCfb_5bf082d29588c07f842ccde3f97243ea_4.png
+```
+
+## 获取某个任务结果
+
+从`add()`方法返回的`Mission`对象,可查看该任务执行情况。
+
+`Mission`对象属性:
+
+- id:任务 id
+- file_name:要保存的文件名
+- path:要保存的路径
+- data:任务数据
+- state:任务状态,有`'waiting'`、`'running'`、`'done'`三种
+- rate:任务进度,以百分比显示
+- info:任务信息,成功会返回文件绝对路径,失败会显示原因
+- result:任务结果,`True`表示成功,`False`表示失败,`None`表示跳过
+
+```python
+mission = page.download.add(url)
+print(mission.state)
+```
+
+输出:
+
+```python
+running
+```
+
+## 下载设置
+
+可使用以下属性进行配置:
+
+```python
+# 设置线程数,只能在没有任务在运行的时候进行
+page.download.roads = 20
+
+# 大文件分块大小,默认 20MB
+page.downloadd.block_size = '50M'
+
+# 设置保存路径,设置后每个任务会使用这个路径,也可添加任务时单独设置
+page.download.goal_path = r'D:\tmp'
+
+# 设置重试次数,初始为继承 page 的 retry_times 属性
+page.download.retry = 5
+
+# 设置失败重试间隔,初始为继承 page 的 retry_interval 属性
+page.download.interval = 2
+
+# 设置存在文件名冲突时的处理方式,可选 'skip', 'overwrite', 'rename'
+page.download.file_exists = 'skip'
+```
+
+?> **Tips:**
重试次数和间隔在初始化时继承页面对象的`retry_times`和`retry_interval`属性,可用上面例子的方法对下载的重试次数和间隔进行设置,设置后不会影响页面对象的设置。
diff --git a/docs/使用方法/获取元素信息.md b/docs/使用方法/获取元素信息.md
index 311f105..fcbaf5b 100644
--- a/docs/使用方法/获取元素信息.md
+++ b/docs/使用方法/获取元素信息.md
@@ -53,8 +53,6 @@ html = ele.html
"""
```
-
-
## inner_html
此属性返回元素的`innerHTML`文本。
@@ -68,8 +66,6 @@ Hello World!
"""
```
-
-
## tag
此属性返回元素的标签名。
@@ -79,8 +75,6 @@ tag = ele.tag
# 返回:div
```
-
-
## text
此属性返回元素内所有文本组合成的字符串。
@@ -94,8 +88,6 @@ Hello World!
"""
```
-
-
## raw_text
此属性返回元素内原始文本。
@@ -105,13 +97,11 @@ text = ele.raw_text
"""返回(注意保留了元素间的空格和换行):
Hello World!
行元素
-
+
"""
```
-
-
## texts()
此方法返回元素内所有直接子节点的文本,包括元素和文本节点。 它有一个参数`text_node_only`,为`True`时则只获取只返回文本节点。这个方法适用于获取文本节点和元素节点混排的情况。
@@ -376,4 +366,3 @@ displayed = ele.is_displayed()
## is_valid()
与`DriverElement`一致。
-
diff --git a/docs/使用方法/获取网页信息.md b/docs/使用方法/获取网页信息.md
index 5c09d66..2498d03 100644
--- a/docs/使用方法/获取网页信息.md
+++ b/docs/使用方法/获取网页信息.md
@@ -149,11 +149,14 @@ print(page.timeouts)
此属性以列表形式返回当前浏览器所有标签页的 handle。
+!> **注意:**
+以下情况会导致获取到的顺序与视觉效果不一致:1、自动化过程中手动点击标签页;2、浏览器被接管时已打开一个以上标签页。
+
## current_tab_index
此属性返回当前标签页的序号。
-!> **注意:**
自动化过程中若手动点击标签页,会使被点击标签页的 handle 排到首位,从而导致排序与视觉效果不一致。
+!> **注意:**
以下情况会导致获取到的排序号与视觉效果不一致:1、自动化过程中手动点击标签页;2、浏览器被接管时已打开一个以上标签页。
## current_tab_handle
@@ -176,4 +179,3 @@ print(page.timeouts)
- path: 下载文件夹路径,默认从配置信息读取
返回:下载中的文件列表
-
diff --git a/docs/使用方法/页面操作.md b/docs/使用方法/页面操作.md
index 7853115..fcca738 100644
--- a/docs/使用方法/页面操作.md
+++ b/docs/使用方法/页面操作.md
@@ -17,8 +17,6 @@
!> **注意:**
s 模式转 d 模式时,若浏览器当前网址域名和 s 模式不一样,必定会跳转。
-
-
参数:
- mode:目标模式字符串,`'s'`或`'d'`,默认转换到另一种
@@ -299,7 +297,7 @@ page.to_frame(iframe)
返回:None
-!> **注意:**
自动化过程中若手动点击标签页,会使被点击标签页的 handle 排到首位,从而导致排序与视觉效果不一致。
+!> **注意:**
以下情况会导致获取到的排序号与视觉效果不一致:1、自动化过程中手动点击标签页;2、浏览器被接管时已打开一个以上标签页。
```python
# 跳转到第一个标签页
@@ -327,7 +325,7 @@ page.create_tab('http://www.baidu.com')
此方法用于关闭指定的标签页,标签页可以是序号或 handle 值,可关闭多个。默认关闭当前的。
-!> **注意:**
当程序使用的是接管的浏览器,获取到的 handle 顺序和视觉效果不一致,不能按序号关闭。
+!> **注意:**
以下情况会导致获取到的排序号与视觉效果不一致,不能按序号关闭:1、自动化过程中手动点击标签页;2、浏览器被接管时已打开一个以上标签页。
参数:
@@ -347,7 +345,7 @@ page.close_tabs((0, 2))
此方法用于关闭指定标签页以外的标签页,标签页可以是序号或 handle 值,可保留多个。默认保留当前的。
-!> **注意:**
当程序使用的是接管的浏览器,获取到的 handle 顺序和视觉效果不一致,不能按序号关闭。
+!> **注意:**
以下情况会导致获取到的排序号与视觉效果不一致,不能按序号关闭:1、自动化过程中手动点击标签页;2、浏览器被接管时已打开一个以上标签页。
参数:
diff --git a/requirements.txt b/requirements.txt
index 3a9fa48..bd5ed06 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,4 @@
-selenium
+selenium>=4.1
requests
tldextract
lxml
diff --git a/setup.py b/setup.py
index c264a6e..c8ed628 100644
--- a/setup.py
+++ b/setup.py
@@ -6,7 +6,7 @@ with open("README.md", "r", encoding='utf-8') as fh:
setup(
name="DrissionPage",
- version="2.5.9",
+ version="2.6.0",
author="g1879",
author_email="g1879@qq.com",
description="A module that integrates selenium and requests session, encapsulates common page operations.",
@@ -18,7 +18,7 @@ setup(
include_package_data=True,
packages=find_packages(),
install_requires=[
- "selenium",
+ "selenium>=4.1",
"lxml",
"tldextract",
"requests",