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`属性,可用上面例子的方法对下载的重试次数和间隔进行设置,设置后不会影响页面对象的设置。