Selenium实战案例1:论文pdf自动下载

server/2025/2/23 0:45:46/

        在上一篇文章中,我们介绍了Selenium的基础用法和一些常见技巧。今天,我们将通过中国科学:信息科学网站内当前目录论文下载这一实战案例来进一步展示Selenium的web自动化流程。

目录

中国科学:信息科学当期目录论文下载

1.网页内容分析

2.下载流程

检测浏览器内文件下载完毕后退出webdriver        

解压下载的zip文件

完整代码


中国科学:信息科学当期目录论文下载

https://www.sciengine.com/SSI/issuehttps://www.sciengine.com/SSI/issue中国科学:信息科学官网。

1.网页内容分析

        网页内容的分析是web自动化中的关键一步。通过分析网页结构,我们可以确定需要抓取的数据位置以及操作元素的方式。

        与爬虫不同的是,web自动化通常是对浏览器渲染后的html网页直接进行操作,因此,我们不需要像爬虫那样进行抓包分析,只需要在原网页中定位元素并进行相应的操作即可。


 中国科学信息科学网页源代码

      

         观察网页源代码,可以发现,下载时我们主要用到的两个组件是全选下载pdf,且这两个组件均为div元素,具有class_name属性,那么在代码中,我们便可以先定位到全选下载pdf 这两个div,接着按照顺序点击即可。

2.下载流程

        先不着急写代码,我们先手动操作一番,看一下整个流程是什么样子。

        

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

        每个文章的标题都在classname为title的div内的span标签下,我们分别复制第一个文章与最后一个文章的标题的XPATH:

python">'//*[@id="journal-list"]/div[1]/div[1]/div[4]/div/div[1]/div/div[2]/div[2]/a/span'
python">'//*[@id="journal-list"]/div[1]/div[1]/div[4]/div/div[13]/div/div[2]/div[2]/a/span'

      不难发现,对于第i个文章的标题,其XPATH应该为:

python">'//*[@id="journal-list"]/div[1]/div[1]/div[4]/div/div[{i}]/div/div[2]/div[2]/a/span'

     

  那么,为了功能更完善一些,我们还可以在点击全选之后按照出现的数量,遍历查找上述的XPATH下的内容的text属性,这些text便是所有的论文标题,我们还可以将其写入到txt中,与下载的论文一起保存到本地。

python">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立即关闭,不会等待多余时长。

python">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模块即可

python">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文件名':即可。

完整代码

python">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()

 运行结果


http://www.ppmy.cn/server/169986.html

相关文章

解决DeepSeek服务器繁忙问题的实用指南

目录 简述 1. 关于服务器繁忙 1.1 服务器负载与资源限制 1.2 会话管理与连接机制 1.3 客户端配置与网络问题 2. 关于DeepSeek服务的备用选项 2.1 纳米AI搜索 2.2 硅基流动 2.3 秘塔AI搜索 2.4 字节跳动火山引擎 2.5 百度云千帆 2.6 英伟达NIM 2.7 Groq 2.8 Firew…

嵌入式0xDEADBEEF

在嵌入式系统中,0xDEADBEEF 是一个常见的“魔数”(magic number),通常用于调试和内存管理。它的含义和用途如下: 1. 调试用途 未初始化内存的标记:在调试时,0xDEADBEEF 常用于标记未初始化或已…

腾讯云DeepSeek大模型应用搭建指南

📍2月8日,腾讯云宣布上线DeepSeek-R1及V3原版模型API接口,通过强大的公有云服务,腾讯云可以为用户提供稳定优质的服务。同时,腾讯云旗下大模型知识应用开发平台知识引擎也接入了DeepSeek-R1及V3这两款模型,…

docker 和 Quay.io的关系

Docker 和 Quay.io 存在紧密的关联,它们在容器技术生态系统中扮演着不同但相互协作的角色,下面从多个方面为你详细介绍它们的关系: 概念层面 Docker:是一个用于开发、部署和运行应用程序的开源平台,基于容器化技术。它允许开发者将应用及其依赖项打包到一个独立的容器中,…

如何调用 DeepSeek API:详细教程与示例

目录 一、准备工作 二、DeepSeek API 调用步骤 1. 选择 API 端点 2. 构建 API 请求 3. 发送请求并处理响应 三、Python 示例:调用 DeepSeek API 1. 安装依赖 2. 编写代码 3. 运行代码 四、常见问题及解决方法 1. API 调用返回 401 错误 2. API 调用返回…

RabbitMQ 消息队列 优化发送邮件

express 发送邮件 最简单的异步发送邮件方法为何要使用 RabbitMQ?如何在 Node 项目中集成 RabbitMQ? 一、 不用 await 发送邮件 在实际开发之前,不妨先思考下,我们最终的目的是为了让邮件异步发送。那发送邮件这里有个await&am…

stm32单片机个人学习笔记16(SPI通信协议)

前言 本篇文章属于stm32单片机(以下简称单片机)的学习笔记,来源于B站教学视频。下面是这位up主的视频链接。本文为个人学习笔记,只能做参考,细节方面建议观看视频,肯定受益匪浅。 STM32入门教程-2023版 细…

Golang访问Google Sheet

步骤 1、创建Project https://console.cloud.google.com/welcome?hlzh-cn&projectvelvety-being-444310-c1 2、启用Google Sheet API https://console.cloud.google.com/apis/library?hlzh-cn&projectvelvety-being-444310-c1 3、创建服务账号 https://conso…