diff --git a/DrissionPage/__init__.py b/DrissionPage/__init__.py index 7f71de5..1d6b9d2 100644 --- a/DrissionPage/__init__.py +++ b/DrissionPage/__init__.py @@ -20,7 +20,3 @@ from .keys import Keys from .mix_page import MixPage from .drission import Drission from .configs.driver_options import DriverOptions - -from warnings import filterwarnings - -filterwarnings('ignore') diff --git a/DrissionPage/chromium_page.py b/DrissionPage/chromium_page.py index 16e1d5f..6679a4d 100644 --- a/DrissionPage/chromium_page.py +++ b/DrissionPage/chromium_page.py @@ -7,11 +7,12 @@ from pathlib import Path from platform import system from threading import Thread from time import perf_counter, sleep +from warnings import warn from requests import Session from .chromium_base import ChromiumBase, Timeout -from .chromium_driver import ChromiumDriver +from .chromium_driver import ChromiumDriver, CallMethodException from .chromium_tab import ChromiumTab from .configs.chromium_options import ChromiumOptions from .configs.driver_options import DriverOptions @@ -30,6 +31,7 @@ class ChromiumPage(ChromiumBase): :param timeout: 超时时间 """ self._download_set = None + self._download_path = None super().__init__(addr_driver_opts, tab_id, timeout) def _connect_browser(self, addr_driver_opts=None, tab_id=None): @@ -93,10 +95,21 @@ class ChromiumPage(ChromiumBase): :return: None """ super()._init_page(tab_id) + ws = self._control_session.get(f'http://{self.address}/json/version').json()['webSocketDebuggerUrl'] + self._browser_driver = ChromiumDriver(ws.split('/')[-1], 'browser', self.address) + self._browser_driver.start() self._tab_obj.Page.javascriptDialogOpening = self._on_alert_open self._tab_obj.Page.javascriptDialogClosed = self._on_alert_close self._main_tab = self.tab_id - self.download_set.by_DownloadKit() + try: + self.download_set.by_DownloadKit() + except RuntimeError: + pass + + @property + def browser_driver(self): + """返回用于控制浏览器cdp的driver""" + return self._browser_driver @property def tabs_count(self): @@ -106,7 +119,7 @@ class ChromiumPage(ChromiumBase): @property def tabs(self): """返回所有标签页id组成的列表""" - j = self._control_session.get(f'http://{self.address}/json').json() + j = self._control_session.get(f'http://{self.address}/json').json() # 不要改用cdp return [i['id'] for i in j if i['type'] == 'page'] @property @@ -388,6 +401,9 @@ class ChromiumDownloadSetter(DownloadSetter): """用于设置下载参数的类""" def __init__(self, page): + """ + :param page: ChromiumPage对象 + """ super().__init__(page) self._behavior = 'allow' self._download_th = None @@ -419,24 +435,33 @@ class ChromiumDownloadSetter(DownloadSetter): path = str(path) self._page._download_path = path try: - self._page.run_cdp('Browser.setDownloadBehavior', behavior='allow', downloadPath=path, not_change=True) - except: + self._page.browser_driver.Browser.setDownloadBehavior(behavior='allow', downloadPath=path, + eventsEnabled=True) + except CallMethodException: + warn('\n您的浏览器版本太低,用新标签页下载文件可能崩溃,建议升级。') self._page.run_cdp('Page.setDownloadBehavior', behavior='allow', downloadPath=path, not_change=True) self.DownloadKit.goal_path = path def by_browser(self): """设置使用浏览器下载文件""" - self._page.driver.Page.downloadWillBegin = self._download_by_browser - self._page.driver.Browser.downloadWillBegin = self._download_by_browser - self._page.driver.Browser.setDownloadBehavior(behavior='allow', downloadPath=self._page.download_path) + try: + self._page.browser_driver.Browser.setDownloadBehavior(behavior='allow', eventsEnabled=True, + downloadPath=self._page.download_path) + self._page.browser_driver.Browser.downloadWillBegin = self._download_by_browser + except CallMethodException: + self._page.driver.Page.setDownloadBehavior(behavior='allow', downloadPath=self._page.download_path) + self._page.driver.Page.downloadWillBegin = self._download_by_browser + self._behavior = 'allow' def by_DownloadKit(self): """设置使用DownloadKit下载文件""" - self._page.driver.Page.downloadWillBegin = self._download_by_DownloadKit - self._page.driver.Browser.downloadWillBegin = self._download_by_DownloadKit - self._page.driver.Browser.setDownloadBehavior(behavior='deny') + try: + self._page.browser_driver.Browser.setDownloadBehavior(behavior='deny', eventsEnabled=True) + self._page.browser_driver.Browser.downloadWillBegin = self._download_by_DownloadKit + except CallMethodException: + raise RuntimeError('您的浏览器版本太低,不支持此方法,请升级。') self._behavior = 'deny' def wait_download_begin(self, timeout=None): @@ -465,7 +490,7 @@ class ChromiumDownloadSetter(DownloadSetter): def _download_by_DownloadKit(self, **kwargs): """拦截浏览器下载并用downloadKit下载""" - self._page.run_cdp('Browser.cancelDownload', guid=kwargs['guid'], not_change=True) + self._page.browser_driver.Browser.cancelDownload(guid=kwargs['guid']) self._page.download.add(file_url=kwargs['url'], goal_path=self._page.download_path, rename=kwargs['suggestedFilename']) if self._download_th is None or not self._download_th.is_alive(): diff --git a/DrissionPage/chromium_page.pyi b/DrissionPage/chromium_page.pyi index a0bbaca..52691cd 100644 --- a/DrissionPage/chromium_page.pyi +++ b/DrissionPage/chromium_page.pyi @@ -32,6 +32,7 @@ class ChromiumPage(ChromiumBase): self._alert: Alert = ... self._download_path: str = ... self._download_set: ChromiumDownloadSetter = ... + self._browser_driver: ChromiumDriver = ... def _connect_browser(self, addr_driver_opts: Union[str, ChromiumDriver, DriverOptions] = None, @@ -43,6 +44,9 @@ class ChromiumPage(ChromiumBase): def _init_page(self, tab_id: str = None) -> None: ... + @property + def browser_driver(self) -> ChromiumDriver: ... + @property def tabs_count(self) -> int: ... diff --git a/DrissionPage/easy_set.py b/DrissionPage/easy_set.py index fd856ea..d16bbd5 100644 --- a/DrissionPage/easy_set.py +++ b/DrissionPage/easy_set.py @@ -58,7 +58,7 @@ def set_paths(driver_path=None, om.set_item('paths', 'chromedriver_path', format_path(driver_path)) if chrome_path is not None: - om.set_item('chrome_options', 'binary_location', format_path(browser_path)) + om.set_item('chrome_options', 'binary_location', format_path(chrome_path)) if browser_path is not None: om.set_item('chrome_options', 'binary_location', format_path(browser_path)) diff --git a/DrissionPage/web_page.py b/DrissionPage/web_page.py index 4303718..e991ace 100644 --- a/DrissionPage/web_page.py +++ b/DrissionPage/web_page.py @@ -5,13 +5,14 @@ """ from pathlib import Path from time import sleep +from warnings import warn from requests import Session from tldextract import extract from .base import BasePage from .chromium_base import ChromiumBase, Timeout -from .chromium_driver import ChromiumDriver +from .chromium_driver import ChromiumDriver, CallMethodException from .chromium_page import ChromiumPage, ChromiumDownloadSetter from .configs.chromium_options import ChromiumOptions from .configs.driver_options import DriverOptions @@ -507,9 +508,10 @@ class WebPageDownloadSetter(ChromiumDownloadSetter): if self._page._has_driver: try: - self._page.run_cdp('Browser.setDownloadBehavior', behavior=self._behavior, downloadPath=path, - not_change=True) - except: + self._page.browser_driver.Browser.setDownloadBehavior(behavior=self._behavior, downloadPath=path, + eventsEnabled=True) + except CallMethodException: + warn('\n您的浏览器版本太低,用新标签页下载文件可能崩溃,建议升级。') self._page.run_cdp('Page.setDownloadBehavior', behavior=self._behavior, downloadPath=path, not_change=True) @@ -517,15 +519,26 @@ class WebPageDownloadSetter(ChromiumDownloadSetter): """设置使用浏览器下载文件""" if not self._page._has_driver: raise RuntimeError('浏览器未连接。') - self._page.driver.Page.downloadWillBegin = self._download_by_browser - self._page.driver.Browser.downloadWillBegin = self._download_by_browser - self._page.driver.Browser.setDownloadBehavior(behavior='allow', downloadPath=self._page.download_path) + + try: + self._page.browser_driver.Browser.setDownloadBehavior(behavior='allow', eventsEnabled=True, + downloadPath=self._page.download_path) + self._page.browser_driver.Browser.downloadWillBegin = self._download_by_browser + + except CallMethodException: + warn('\n您的浏览器版本太低,用新标签页下载文件可能崩溃,建议升级。') + self._page.driver.Page.setDownloadBehavior(behavior='allow', downloadPath=self._page.download_path) + self._page.driver.Page.downloadWillBegin = self._download_by_browser + self._behavior = 'allow' def by_DownloadKit(self): """设置使用DownloadKit下载文件""" if self._page._has_driver: - self._page.driver.Page.downloadWillBegin = self._download_by_DownloadKit - self._page.driver.Browser.downloadWillBegin = self._download_by_DownloadKit - self._page.driver.Browser.setDownloadBehavior(behavior='deny') + try: + self._page.browser_driver.Browser.setDownloadBehavior(behavior='deny', eventsEnabled=True) + self._page.browser_driver.Browser.downloadWillBegin = self._download_by_DownloadKit + except CallMethodException: + raise RuntimeError('您的浏览器版本太低,不支持此方法,请升级。') + self._behavior = 'deny' diff --git a/docs/WebPage使用方法/3.1创建页面对象.md b/docs/WebPage使用方法/3.1创建页面对象.md index bc43c21..9211324 100644 --- a/docs/WebPage使用方法/3.1创建页面对象.md +++ b/docs/WebPage使用方法/3.1创建页面对象.md @@ -37,11 +37,11 @@ page = SessionPage() # ✔️ 通过配置信息创建 -本库有两种管理配置信息的对象,`DriverOptions`和`SessionOptions`,分别对应控制浏览器和收发数据包的配置。须要时,可以创建相应的配置对象进行设置。 +本库有两种管理配置信息的对象,`ChromiumOptions`和`SessionOptions`,分别对应控制浏览器和收发数据包的配置。须要时,可以创建相应的配置对象进行设置。 -## 📍 `DriverOptions` +## 📍 `ChromiumOptions` -`DriverOptions`用于管理创建浏览器时的配置,内置了常用的配置,并能实现链式操作。详细使用方法见“启动配置”一节。 +`ChromiumOptions`用于管理创建浏览器时的配置,内置了常用的配置,并能实现链式操作。详细使用方法见“启动配置”一节。 | 初始化参数 | 类型 | 默认值 | 说明 | | ----------- | ------ | ------ | ------------------------ | @@ -51,11 +51,11 @@ page = SessionPage() !>**注意:**
浏览器创建后再修改这个配置是没有效果的。 ```python -# 导入 DriverOptions -from DrissionPage import WebPage, DriverOptions +# 导入 ChromiumOptions +from DrissionPage import WebPage, ChromiumOptions # 创建浏览器配置对象,指定浏览器路径 -do = DriverOptions().set_paths(browser_path=r'D:\chrome.exe') +do = ChromiumOptions().set_paths(browser_path=r'D:\chrome.exe') # 用该配置创建页面对象 page = WebPage(driver_or_options=do) ``` @@ -192,9 +192,9 @@ D:\chrome.exe --remote-debugging-port=9222 程序代码: ```python -from DrissionPage import WebPage, DriverOptions +from DrissionPage import WebPage, ChromiumOptions -do = DriverOptions().set_paths(local_port=9222) +do = ChromiumOptions().set_paths(local_port=9222) page = WebPage(driver_or_options=do) ``` @@ -216,18 +216,18 @@ page = WebPage(driver_or_options=do) ## 📍 用程序启动的浏览器 -如果想要同时操作多个浏览器,或者自己在使用其中一个上网,同时控制另外几个跑自动化,就须要给这些被程序控制的浏览器设置单独的**端口**和**用户文件夹**,否则会造成冲突。具体用`DriverOptions`对象进行设置,示例如下: +如果想要同时操作多个浏览器,或者自己在使用其中一个上网,同时控制另外几个跑自动化,就须要给这些被程序控制的浏览器设置单独的**端口**和**用户文件夹**,否则会造成冲突。具体用`ChromiumOptions`对象进行设置,示例如下: ```python -from DrissionPage import ChromiumPage, DriverOptions +from DrissionPage import ChromiumPage, ChromiumOptions # 创建多个配置对象,每个指定不同的端口号和用户文件夹路径 -do1 = DriverOptions().set_paths(local_port=9111, user_data_path=r'D:\data1') -do2 = DriverOptions().set_paths(local_port=9222, user_data_path=r'D:\data2') +do1 = ChromiumOptions().set_paths(local_port=9111, user_data_path=r'D:\data1') +do2 = ChromiumOptions().set_paths(local_port=9222, user_data_path=r'D:\data2') # 创建多个页面对象 -page1 = ChromiumPage(driver_or_options=do1) -page2 = ChromiumPage(driver_or_options=do2) +page1 = ChromiumPage(addr_driver_opts=do1) +page2 = ChromiumPage(addr_driver_opts=do2) # 每个页面对象控制一个浏览器 page1.get('https://www.baidu.com') @@ -255,24 +255,24 @@ bat 文件2 程序代码: ```python -from DrissionPage import ChromiumPage, DriverOptions +from DrissionPage import ChromiumPage, ChromiumOptions -do1 = DriverOptions().set_paths(local_port=9111) -do2 = DriverOptions().set_paths(local_port=9222) +do1 = ChromiumOptions().set_paths(local_port=9111) +do2 = ChromiumOptions().set_paths(local_port=9222) page1 = ChromiumPage(addr_driver_opts=do1) -page2 = ChromiumPage(driver_or_options=do2) +page2 = ChromiumPage(addr_driver_opts=do2) ``` # ✔️ 页面对象初始化 API ## 📍 `ChromiumPage` -`ChroumiumPage`对象纯粹用于操作浏览器,不能切换模式。一个该对象对应的是浏览器上一个标签页。 +`ChroumiumPage`对象纯粹用于操作浏览器,不能切换模式。一个该对象对应一个浏览器。 | 初始化参数 | 类型 | 默认值 | 说明 | | ------------------ | -------------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------- | -| `addr_driver_opts` | `str`
`ChromiumDriver`
`DriverOptions` | `None` | 浏览器启动配置或接管信息。传入' ip:port' 字符串或`ChromiumDriver`时接管浏览器;传入`DriverOptions`时按配置启动浏览器;为`None`时使用配置文件配置启动浏览器 | +| `addr_driver_opts` | `str`
`ChromiumDriver` | `None` | 浏览器启动配置或接管信息。传入' ip:port' 字符串或`ChromiumDriver`时接管浏览器;传入`DriverOptions`时按配置启动浏览器;为`None`时使用配置文件配置启动浏览器 | | `tab_id` | `str` | `None` | 要控制的标签页id,用于 d 模式,为`None`则控制激活的标签页 | | `timeout` | `float` | `None` | 整体超时时间,为`None`则从配置文件中读取 | @@ -294,7 +294,7 @@ page2 = ChromiumPage(driver_or_options=do2) | `mode` | `str` | `'d'` | 启动时的模式,只能传入`'d'`或`'s'` | | `timeout` | `float` | `None` | 整体超时时间,为`None`则从配置文件中读取 | | `tab_id` | `str` | `None` | 要控制的标签页id,用于 d 模式,为`None`则控制激活的标签页 | -| `driver_or_options` | `ChromiumDriver`
`DriverOptions`
`bool` | `None` | 浏览器控制对象或浏览器启动配置对象;为`None`时使用 ini 文件配置;为`False`时不读取 ini 文件。 | +| `driver_or_options` | `ChromiumDriver`
`bool` | `None` | 浏览器控制对象或浏览器启动配置对象;为`None`时使用 ini 文件配置;为`False`时不读取 ini 文件。 | | `session_or_options` | `Session`
`SessionOptions`
`bool` | `None` | 收发数据包对象或`Session`启动配置对象;为`None`时使用 ini 文件配置;为`False`时不读取 ini 文件。 | **◽ 说明:** diff --git a/docs/imgs/baidu_1.jpg b/docs/imgs/baidu_1.jpg new file mode 100644 index 0000000..39984b1 Binary files /dev/null and b/docs/imgs/baidu_1.jpg differ diff --git a/docs/imgs/baidu_2.jpg b/docs/imgs/baidu_2.jpg new file mode 100644 index 0000000..e6af1bc Binary files /dev/null and b/docs/imgs/baidu_2.jpg differ diff --git a/docs/入门指南/准备工作.md b/docs/入门指南/准备工作.md index 9dadd88..998a08b 100644 --- a/docs/入门指南/准备工作.md +++ b/docs/入门指南/准备工作.md @@ -35,7 +35,7 @@ page.get('https://www.baidu.com') ```python from DrissionPage.easy_set import set_paths -set_paths(chrome_path=r'这里修改为您的Chrome浏览器exe文件路径', check_version=False) +set_paths(browser_path=r'这里修改为您的Chrome浏览器exe文件路径') ``` 执行这段代码会记录您电脑的 Chrome 浏览器路径到配置文件。 diff --git a/docs/入门指南/安装和导入.md b/docs/入门指南/安装和导入.md index d22614d..624a26a 100644 --- a/docs/入门指南/安装和导入.md +++ b/docs/入门指南/安装和导入.md @@ -38,7 +38,7 @@ from DrissionPage import ChromiumPage from DrissionPage import SessionPage # 浏览启动参数管理器,用于控制浏览器启动参数 -from DrissionPage import DriverOptions +from DrissionPage import ChromiumOptions # Session对象启动参数管理器,用于控制Session对象启动参数 from DrissionPage import SessionOptions diff --git a/docs/启动配置/Session启动配置.md b/docs/启动配置/Session启动配置.md index 0a925ab..9ff1668 100644 --- a/docs/启动配置/Session启动配置.md +++ b/docs/启动配置/Session启动配置.md @@ -1,5 +1,5 @@ `SessionOptions`对象用于管理`Session`对象连接配置。 -其使用逻辑与`DriverOptions`相似。 +其使用逻辑与`ChromiumOptions`相似。 !> **注意:**
`SessionOptions`仅用于管理启动配置,程序启动后再修改无效。 diff --git a/docs/启动配置/使用配置文件.md b/docs/启动配置/使用配置文件.md index 4127431..7f46cd1 100644 --- a/docs/启动配置/使用配置文件.md +++ b/docs/启动配置/使用配置文件.md @@ -96,12 +96,12 @@ page = WebPage() 这种方式一般用于加载配置后须要进一步修改。 ```python -from DrissionPage import DriverOptions, SessionOptions, WebPage +from DrissionPage import ChromiumOptions, SessionOptions, WebPage -do = DriverOptions(ini_path='D:\\setting.ini') +do = ChromiumOptions(ini_path='D:\\setting.ini') so = SessionOptions(ini_path='D:\\setting.ini') -page = WebPage(driver_or_options=do, session_or_option=so) +page = WebPage(driver_or_options=do, session_or_options=so) ``` ## 📍 使用 Drission 对象加载 @@ -120,9 +120,9 @@ page = MixPage(drission=ds) # ✔️ 保存/另存 ini 文件 ```python -from DrissionPage import DriverOptions +from DrissionPage import ChromiumOptions -do = DriverOptions() +do = ChromiumOptions() # 设置不加载图片 do.set_no_imgs() diff --git a/docs/启动配置/概述.md b/docs/启动配置/概述.md index 30bc658..76fbc08 100644 --- a/docs/启动配置/概述.md +++ b/docs/启动配置/概述.md @@ -2,6 +2,6 @@ 因此,本库提供了一些方法简化其使用。 - 使用 ini 文件记录常用配置,使配置便于复用,无须在代码中编写繁琐的配置。 -- 使用`DriverOptions`对象管理浏览器配置。 +- 使用`ChromiumOptions`对象管理浏览器配置。 - 使用`SessionOptions`对象管理`Session`对象配置。 - 提供 easy_set 方法,专门用于对 ini 文件中常用配置进行管理,简化配置操作。 \ No newline at end of file diff --git a/docs/版本历史.md b/docs/版本历史.md index 0e32d6d..1a221ea 100644 --- a/docs/版本历史.md +++ b/docs/版本历史.md @@ -1,4 +1,4 @@ -# v3.1.0 +# v3.1.1 - 增强下载功能 diff --git a/docs/进阶使用/打包程序.md b/docs/进阶使用/打包程序.md index 2aeec14..48d154f 100644 --- a/docs/进阶使用/打包程序.md +++ b/docs/进阶使用/打包程序.md @@ -15,9 +15,9 @@ `WebPage`: ```python -from DrissionPage import WebPage, DriverOptions, SessionOptions +from DrissionPage import WebPage, ChromiumOptions, SessionOptions -do = DriverOptions(ini_path=r'.\configs.ini') +do = ChromiumOptions(ini_path=r'.\configs.ini') so = SessionOptions(ini_path=r'.\configs.ini') page = WebPage(driver_or_options=do, session_or_options=so) ``` @@ -38,9 +38,9 @@ page = MixPage(drission=drission) `WebPage`: ```python -from DrissionPage import WebPage, DriverOptions, SessionOptions +from DrissionPage import WebPage, ChromiumOptions, SessionOptions -do = DriverOptions(read_file=False) # 不读取文件方式新建配置对象 +do = ChromiumOptions(read_file=False) # 不读取文件方式新建配置对象 so = SessionOptions(read_file=False) do.set_paths(chrome_path=r'.\chrome.exe') # 输入配置信息 @@ -70,11 +70,11 @@ page = WebPage(driver_or_options=do, session_or_options=False) 通常,我会把一个绿色浏览器和打包后的 exe 文件放在一起,程序中用相对路径指向该浏览器,这样拿到别的电脑也可以正常实用。 ```python -from DrissionPage import WebPage, DriverOptions +from DrissionPage import WebPage, ChromiumOptions -do = DriverOptions(read_file=False).set_paths(local_port='9888', - chrome_path=r'.\Chrome\chrome.exe', - user_data_path=r'.\Chrome\userData') +do = ChromiumOptions(read_file=False).set_paths(local_port='9888', + browser_path=r'.\Chrome\chrome.exe', + user_data_path=r'.\Chrome\userData') page = WebPage(driver_or_options=do, session_or_options=False) # 注意:session_or_options=False @@ -83,5 +83,5 @@ page.get('https://www.baidu.com') 注意以下两点,程序就会跳过读取 ini 文件: -- `DriverOptions()`里要设置`read_file=False` -- 如果不传入某个模式的配置(示例中为 s 模式),要在`MixPage()`初始化是设置对应参数为`False` +- `ChromiumOptions()`里要设置`read_file=False` +- 如果不传入某个模式的配置(示例中为 s 模式),要在页面对象初始化时设置对应参数为`False` diff --git a/setup.py b/setup.py index b7788ca..f6c3c70 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="3.1.0", + version="3.1.1", author="g1879", author_email="g1879@qq.com", description="A module that integrates selenium and requests session, encapsulates common page operations.",