Selenium实战案例1:论文pdf自动下载
在上一篇文章中,我们介绍了Selenium的基础用法和一些常见技巧。今天,我们将通过中国科学:信息科学网站内当前目录论文下载这一实战案例来进一步展示Selenium的web自动化流程。
目录
中国科学:信息科学当期目录论文下载
1.网页内容分析
2.下载流程
检测浏览器内文件下载完毕后退出webdriver
解压下载的zip文件
完整代码
中国科学:信息科学当期目录论文下载
https://www.sciengine.com/SSI/issue
https://www.sciengine.com/SSI/issue中国科学:信息科学官网。
1.网页内容分析
网页内容的分析是web自动化中的关键一步。通过分析网页结构,我们可以确定需要抓取的数据位置以及操作元素的方式。
与爬虫不同的是,web自动化通常是对浏览器渲染后的html网页直接进行操作,因此,我们不需要像爬虫那样进行抓包分析,只需要在原网页中定位元素并进行相应的操作即可。

中国科学信息科学网页源代码
观察网页源代码,可以发现,下载时我们主要用到的两个组件是全选与下载pdf,且这两个组件均为div元素,具有class_name属性,那么在代码中,我们便可以先定位到全选与下载pdf 这两个div,接着按照顺序点击即可。
2.下载流程
先不着急写代码,我们先手动操作一番,看一下整个流程是什么样子。

按下全选后,所有文章被选中,且会在下方出现已选中13结果的字样,表示待下载的文件数量。

每个文章的标题都在classname为title的div内的span标签下,我们分别复制第一个文章与最后一个文章的标题的XPATH:
'//*[@id="journal-list"]/div[1]/div[1]/div[4]/div/div[1]/div/div[2]/div[2]/a/span'
'//*[@id="journal-list"]/div[1]/div[1]/div[4]/div/div[13]/div/div[2]/div[2]/a/span'
不难发现,对于第i个文章的标题,其XPATH应该为:
'//*[@id="journal-list"]/div[1]/div[1]/div[4]/div/div[{i}]/div/div[2]/div[2]/a/span'
那么,为了功能更完善一些,我们还可以在点击全选之后按照出现的数量,遍历查找上述的XPATH下的内容的text属性,这些text便是所有的论文标题,我们还可以将其写入到txt中,与下载的论文一起保存到本地。
essay_titles=[]
total_number=browser.find_element(By.XPATH,'//*[@id="selectedArticleNum"]/strong')#定位全选之后弹出的已选中之后的数字total_number=int(total_number.text)#################################查找文章标题for i in range(1,total_number+1):essay_title=browser.find_element(By.XPATH,f'//*[@id="journal-list"]/div[1]/div[1]/div[4]/div/div[{i}]/div/div[2]/div[2]/a/span')essay_titles.append(essay_title.text)#################################将查找到的文章标题写入到与下载文件同路径的位置的txt内full_path=os.path.join(self.download_path,'下载论文列表.txt')with open(full_path,'w',encoding='utf-8') as file:for essay_title in self.essay_titles: file.write(essay_title+'\n')
在按下下载PDF按钮后,页面会暂时的跳转到一个其他url下的空白页面,过一会儿后,文件开始下载,且下载到本地的格式为zip。


按下下载pdf按钮后页面变化
检测浏览器内文件下载完毕后退出webdriver
对于上述两个流程,倘若我们在代码中不加任何等待机制:即等待页面跳转完毕,文件开始下载至文件下载完毕的等待机制。
即使我们在代码中没有写browser.quit()这样的命令,webdriver也会自动关闭的。
这是因为我们的代码中涉及到自动化流程的只有点击全选与下载pdf这两个按钮以及查找文章标题,一旦这三个任务完成后,webdriver是会自动关闭的。
对于上述问题,最简单的思路是使用time.sleep()函数,设置足够多的秒数,保证点击下载pdf按钮后,从文件开始下载至文件下载完毕webdriver不会关闭,这里我已经测试过,使用time.sleep(30)足矣。
但是,这样有点太过于勉强,且不够优雅,有没有更好的解决方案呢?

答案是:有的。
大家在使用谷歌或者Edge浏览器下载文件时,如果在文件下载过程中,中途退出会发现源文件下载取消且中断,并且在下载文件的位置有一个 文件名.crdownload的文件,这是一个临时文件,表示文件在浏览器下载过程中未完全下载完毕,在下载完毕后文件名后缀中的.crdownload会消失。
那么,我们便可以按照下边的方式来进行等待,这样等待的好处是只要文件下载完毕,webdriver立即关闭,不会等待多余时长。
import os
import time
def is_download_finished(download_path):files=os.listdir(download_path)for file in files:if file.endswith('crdownload'):#判断文件夹内是否存在crdownload结尾文件,如果有说明还webdriver内还有文件在下载中return Falsereturn True
while not is_download_finished(download_path):#while循环轮询time.sleep(1)#这里以1s为单位,若对等待时间要求较高,可以更换为0.1-0.5的小数
webdriver.quit()#关闭先前打开的webdriver
等待文件下载完毕代码
到这里就万事大吉了吗?No,No,No。还记得我们前边我们说到的,我们在点击下载pdf后,会有大概5s左右的空闲时间,在这5s内我们会临时跳转到一个新的网页,然后又跳转回到原来的网页,文件开始下载吗?

点击下载pdf后,跳转到空白网页

大概5s后,返回原网页,文件开始下载
对于上述现象,倘若我们在点击下载pdf后,直接使用上边的等待文件下载完毕的代码的话,由于文件还没开始下载,文件夹内也根本没有crdownload结尾的文件,此时代码中is_download_finishe函数会直接返回True,while循环一次也不执行,webdriver直接就退出了。
所以,我们应该等待文件正式下载后再调用上边的代码,这里可以使用time.sleep函数,等待几秒钟页面跳转完毕,当然也可以使用webdriver的current_url属性,先临时保存原先网页url,然后一个while循环判断webdriver.current_url是否等于原来的网页的url来进行判断。为了省事,我们这里就直接使用time.sleep函数进行等待了。
解压下载的zip文件
解压已经下载好的zip文件,我们只需要使用python标准库内置的zipfile模块即可
import os
import zipfile
def extract_zip_file(download_path):#解压zip文件filelist=os.listdir(download_path)for file in filelist:if file.endswith('.zip'):zip_file_path=os.path.join(download_path,file)with zipfile.ZipFile(zip_file_path,'r') as zip:zip.extractall(download_path)
运行上述代码后,给定文件夹下的后缀为zip的文件夹内的内容将被解压到原路径下,注意:若你需要解压指定的zip文件夹,只需要将 if file.endswith('.zip'):更换为if file=='指定的zip文件名':即可。
完整代码
import os
import time
import zipfile
from selenium import webdriver
from selenium.webdriver.edge.options import Options
from selenium.webdriver.common.by import By
class 中国科学():def __init__(self,download_path:str,headless:bool=False):'''Args:download_path:下载文件保存路径headless:是否开启无头模式'''self.download_path=download_pathself.headless=headlessself.essay_titles=[]def extract_zip_file(self):#解压zip文件filelist=os.listdir(self.download_path)for file in filelist:if file.endswith('.zip'):zip_file_path=os.path.join(self.download_path,file)with zipfile.ZipFile(zip_file_path,'r') as zip:zip.extractall(self.download_path)def is_download_finished(self):#判断是否下载完毕files=os.listdir(self.download_path)for file in files:if file.endswith('crdownload'):return Falsereturn Truedef download(self):#下载文件prefs = {'download.default_directory': self.download_path, # 设置默认下载路径"profile.default_content_setting_values.automatic_downloads": True # 允许多文件下载} self.Options=Options()self.Options.add_argument('--disable-blink-features=AutomationControlled')#隐藏自动化控制self.Options.add_argument('--ignore-ssl-errosr')#忽略ssl错误self.Options.add_argument('--ignore-certificate-errors')#忽略证书错误self.Options.add_experimental_option("prefs", prefs)self.Options.add_experimental_option('excludeSwitches', ['enable-logging'])self.Options.add_experimental_option('excludeSwitches',['enable-automation'])#隐藏自动化控制if self.headless:#无头模式运行自动化代码self.Options.add_argument('--headless')self.Options.add_argument('--disable-gpu')else:passself.browser=webdriver.ChromiumEdge(self.Options)self.browser.maximize_window()#webdriver全屏self.browser.get('https://www.sciengine.com/SSI/issue')self.browser.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {#执行一段js代码,隐藏自动化控制"source": """Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"""})select_all=self.browser.find_element(By.CLASS_NAME,'select.borderC2')download_pdf=self.browser.find_element(By.CLASS_NAME,'download.borderC2')self.browser.execute_script('arguments[0].click()',select_all)total_number=self.browser.find_element(By.XPATH,'//*[@id="selectedArticleNum"]/strong')#定位全选之后弹出的已选中之后的数字total_number=int(total_number.text)#################################查找文章标题for i in range(1,total_number+1):essay_title=self.browser.find_element(By.XPATH,f'//*[@id="journal-list"]/div[1]/div[1]/div[4]/div/div[{i}]/div/div[2]/div[2]/a/span')self.essay_titles.append(essay_title.text)#################################将查找到的文章标题写入到与下载文件同路径的位置的txt内full_path=os.path.join(self.download_path,'下载论文列表.txt')with open(full_path,'w',encoding='utf-8') as file:for essay_title in self.essay_titles: file.write(essay_title+'\n')##################################点击下载按钮,等待下载完毕后退出webdriverself.browser.execute_script('arguments[0].click()',download_pdf)time.sleep(7)#等待7s页面跳转完毕while not self.is_download_finished():time.sleep(1)self.browser.quit()self.extract_zip_file()
中国科学(r"E:\OneDrive\Desktop\中国科学信息科学",headless=False).download()

运行结果
相关文章:
Selenium实战案例1:论文pdf自动下载
在上一篇文章中,我们介绍了Selenium的基础用法和一些常见技巧。今天,我们将通过中国科学:信息科学网站内当前目录论文下载这一实战案例来进一步展示Selenium的web自动化流程。 目录 中国科学:信息科学当期目录论文下载 1.网页内…...
前端面试-JavaScript 数据类型检测全解
目录 一、基础检测方法 二、方法深度解析 1. typeof 运算符 2. instanceof 运算符 3. 终极检测方案 三、特殊场景检测方案 四、手写实现原理 1. 通用类型检测函数 2. 改进版数组检测(兼容旧浏览器) 五、常见面试陷阱 六、最佳实践指南 七、扩…...
nginx 反向代理 配置请求路由
nginx | 反向代理 | 配置请求路由 nginx简介 Nginx(发音为“Engine-X”)是一款高性能、开源的 Web 服务器和反向代理服务器,同时也支持邮件代理和负载均衡等功能。它由俄罗斯程序员伊戈尔西索夫(Igor Sysoev)于 2004…...
用户中心项目教程(十)---注册里面的重定向排查和相关的修改
文章目录 1.注册逻辑的设计和实现2.解决自带的这个重定向的问题3.增加属性的相关操作4.关于如何修改页面上面的绿色按钮 1.注册逻辑的设计和实现 上次说到了的是登录功能,我们使用数据库里面存在的这个存在的账户和密码进行登录,但是是无法进行跳转的&a…...
根据音频中的不同讲述人声音进行分离音频 | 基于ai的说话人声音分离项目
0.研究背景 在实际的开发中可能会遇到这样的问题,老板让你把音频中的每个讲话人的声音分离成不同的音频片段。你可以使用au等专业的音频处理软件手动分离。但是这样效率太慢了,现在ai这么发达,我们能否借助ai之力来分离一条音频中的不同的说…...
【单片机】【UDS】 (单帧与多帧) 数据传输
对于使用 CAN 的诊断通信系统,每个单帧 (SF)、 第一帧 (FF)、 连续帧 (CF) 或流控 制帧 (FC) 有 8 字节数据场;其中单帧的 CAN_DL≤8 且第一帧的 FF_DL≤4095;下表 中已定义 每个报文的类型。 CAN FD 帧的数据场支持最大 64 个字节࿰…...
WebXR教学 02 配置开发环境
默认操作系统为Windows 1.VS Code VS Code 是一款轻量级、功能强大的代码编辑器,适用于多种编程语言。 下载 步骤 1:访问 VS Code 官方网站 打开浏览器(如 Chrome、Edge 等)。 在地址栏输入以下网址: https://code.v…...
MySql数据库运维学习笔记
数据库运维常识 DQL、DML、DCL 和 DDL 是 SQL(结构化查询语言)中的四个重要类别,它们分别用于不同类型的数据库操作,下面为你简单明了地解释这四类语句: 1. DQL(数据查询语言,Data Query Langu…...
网络协议相关问题
1. HTTP 与 HTTPS 的区别 HTTP:明文传输,端口80,无加密,易被窃听或篡改。HTTPS:SSL/TLS加密传输,端口443,通过数字证书验证身份,防止中间人攻击。 混合加密:非对称加密交…...
宇树科技13家核心零部件供应商梳理!
2025年2月6日,摩根士丹利(Morgan Stanley)发布最新人形机器人研报:Humanoid 100: Mapping the Humanoid Robot Value Chain(人形机器人100:全球人形机器人产业链梳理)。 Humanoid 100清单清单中…...
Windows 启动 SSH 服务报错 1067
Windows 启动 SSH 服务报错 1067 一、原本安装的 Windows 自带的 SSH 服务 按 Windows 键 -> 设置 -> 系统 -> 可选功能 在 添加的功能 查看是否安装了 OpenSSH 服务 一开始 执行 net start sshd 是可以正常启动的 并且其他机器也可以通过 ssh 访问 这个电脑 但是有…...
kkFileView报错no office manager available
背景 部署环境:虚机Linux系统 发生问题的版本:4.1.0-SNAPSHOT 现象:有的docx文件可以预览,有的不可以。不可以的就怎么打开都不可以(不管你是躺着,站着,坐着,睡着,趴着都不行,哈哈) 报错内容 贴出主要的报错内容步骤: > no office manager available > tr…...
ARMS 助力假面科技研发运维提效,保障极致游戏体验
客户介绍与项目背景 假面科技成立于 2014 年,致力于打造创新的数字产品,火爆一时的“狼人杀”、“谁是卧底”、“足记相机”都是假面科技旗下产品,公司产品总数超过 40 款,覆盖用户数超过 2 亿人。 随着业务的持续发展ÿ…...
趣味数学300题1981版-八个等式、五个5等于24
八个等式 分析:此问题的求解思路是按照最后一步运算的运算符号进行分类。示例中最后一步的运算是除法,只要被除数与除数相等且不为0,就可以得到结果1.因此我们还可以对于结果等于1的情况列出其他的算式。如果保持最后一步运算为除法运算&…...
关闭超时订单和七天自动确认收货+RabbitMQ规范
关闭超时订单 创建订单之后的一段时间内未完成支付而关闭订单的操作,该功能一般要求每笔订单的超时时间是一致的 TTL(Time To Live)存活时间,只能被设置为某个固定的值,不能更改,否则抛出异常 死信&#…...
DDD领域驱动开发第2讲:领域驱动开发在货代订单业务的实践
领域驱动开发在货代订单业务的实践 本文是DDD领域驱动开发第2讲,先讲解当前业务存在哪些问题,什么是DDD,为啥需要使用DDD解决现有业务问题,DDD让技术主动理解业务,通过领域模型将可以描述各个业务领域之间的关系,最后讲解领域驱动开发在货代订单的实践。 文章目录 领域驱…...
【Qt学习】| 如何使用QVariant存储自定义类型
QVariant是Qt框架中的一个通用数据类型,可以存储多种类型的数据,主要作用是提供一种类型安全的方式来存储和传递不同类型的数据,而不需要显示地指定数据类型。 QVariant提供了诸多构造函数可以非常方便地对基础数据类型(如&#x…...
分割 学习笔记cvpr2024
目录 LiteMedSam 模型37m LightM-Unet 500 str 依赖项: MLWnet 73 star memsam 340M 126 star LiteMedSam 模型37m https://github.com/bowang-lab/MedSAM/blob/LiteMedSAM/README.md LightM-Unet 500 str https://github.com/MrBlankness/LightM-UNet/blob model = Li…...
【多模态处理篇一】【 深度解析DeepSeek图文匹配:CLIP模型迁移实战——从原理到落地的保姆级教程】
引言:当CLIP遇到DeepSeek,会发生什么化学反应? 如果说CLIP是OpenAI为多模态领域投下的"原子弹",那DeepSeek的迁移实战方案就是给这颗原子弹装上了精确制导系统。这个组合能让你用一张猫咪表情包搜到全网同类梗图,还能让电商平台自动生成百万级商品描述,甚至帮…...
水果生鲜农产品推荐系统 协同过滤余弦函数推荐水果生鲜农产品 Springboot Vue Element-UI前后端分离 代码+开发文档+视频教程
水果生鲜农产品推荐系统 协同过滤余弦函数推荐水果生鲜农产品 Springboot Vue Element-UI前后端分离 【亮点功能】 1.SpringbootVueElement-UIMysql前后端分离 2.Echarts图表统计数据, 直观展示数据情况 3.发表评论后,用户可以回复评论, 回复的评论可以被再次回复, …...
1.vue使用vite构建初始化项目
npm create vuelatest❯ npm create vuelatest> npx > create-vueVue.js - The Progressive JavaScript Framework✔ Project name: … vue3_test ✔ Add TypeScript? … No / Yes ✔ Add JSX Support? … No / Yes ✔ Add Vue Router for Single Page Application dev…...
在PyCharm中运行Jupyter Notebook的.ipynb文件及其pycharm软件的基础使用
(注意需使用PyCharm专业版,学生、教师可以申请免费使用:https://www.jetbrains.com/shop/eform/students) 1. pycharm2024版汉化 https://blog.csdn.net/m0_74103046/article/details/144560999 2. pycharm中的python控制台和J…...
深度体验通义灵码2.0 AI 程序员
通义灵码2.0 作为一名开发者,我去年就使用过1.0,近期有幸体验了 2.0,这是一款集成了 Deepseek 大模型的智能编码助手。在这次体验中,我深入探索了新功能开发、跨语言编程、单元测试自动生成、图生代码等多个场景,深刻…...
Coroutine协程
cooperation 协作 routine 程序,常规 协程核心:函数能够被挂起suspend,当然也能被回复resume 内置函数:also 返回对象本身 扩展: 内置函数let、also、with、run、apply大大提高你的开发效率! 协程的作用:…...
使用IDEA提交SpringBoot项目到Gitee上
登录Gitee并新建仓库 创建本地仓库 提交本地代码到本地仓库 提交本地代码到远程仓库...
Windows安装MySQL指南
1.下载 下载地址:https://www.mysql.com/downloads/ 下载版本:MySQL Installer for Window 2.安装MySQL 以下只列出需要注意的一些界面,没出现的界面默认继续即可。 1.选择安装类型 提供了多种安装模式,包括默认开发版、仅…...
汽车免拆诊断案例 | 2013 款奔驰 S300L 车起步时车身明显抖动
故障现象 一辆2013款奔驰S300L车,搭载272 946发动机,累计行驶里程约为15万km。车主反映,将挡位置于D挡,稍微释放一点制动踏板,车辆蠕动时车身明显抖动,类似气缸失火时的抖动,又类似手动变速器…...
从0开始:OpenCV入门教程【图像处理基础】
图像处理基础 一、OpenCV主要功能及模块介绍 1、内置数据结构和输入/输出 OpenCV内置了丰富的与图像处理有关的数据结构,如Image、Point、Rectangle等。core模块实现了各种基本的数据结构。imgcodecs模块提供了图像文件的读写功能,用户使用简单的命令…...
区块链相关方法-SWOT分析
1.SWOT 一、定义:一种基于内外部竞争环境和竞争条件下的态势分析,通过对企业的内外环境所形成的优势(Strengths)、劣势(Weaknesses)、机会(Opportunities)和威胁(Threats࿰…...
React 前端框架介绍
什么是 React? React 是一个由 Facebook 开发并维护的开源 JavaScript 库,用于构建用户界面。它主要用于创建交互式用户界Face(UI),尤其是当数据变化时需要更新部分视图时非常有效。React 的核心思想是组件化和声明性编程,这使得开发者可以轻松地创建、组合和重用代码。…...
