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

news/2025/2/22 6:31:57

        在上一篇文章中,我们介绍了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 False
        return 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_path
        self.headless=headless
        self.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 False
        return True
    def 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:
            pass
        self.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')
        #################################
        #点击下载按钮,等待下载完毕后退出webdriver
        self.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.niftyadmin.cn/n/5861804.html

相关文章

DeepSeek赋能AI边缘计算网关,开启智能新时代!

强强联合 在数字化转型浪潮的推动下,边缘计算正成为构建智能化社会的重要基石。作为边缘计算的核心设备,AI 边缘计算网关的性能直接影响着边缘智能应用的落地效果。 近日,计讯物联与 DeepSeek 实现技术融合,将 DeepSeek 强大算法…

XML XML约束 一、XML约束概述

一个XML文档一旦有了约束&#xff0c;那么这个XML文档就只能使用约束中创建的元素及属性。如果约束没有创建<a>元素&#xff0c;那么XML文档就不能使用<a>元素 1 什么是xml约束 因为xml文档是可以自定义元素的&#xff0c;这会让使用xml文档的应用程序无法知道x…

自动化办公|xlwings生成图表

在日常的数据分析和报告生成中&#xff0c;Excel图表是一个非常重要的工具。它能够帮助我们直观地展示数据&#xff0c;发现数据中的规律和趋势。然而&#xff0c;手动创建和调整图表往往耗时且容易出错。幸运的是&#xff0c;借助Python的xlwings库&#xff0c;我们可以自动化…

从0-1搭建mac环境最新版

从0-1搭建mac环境 先查看自己的芯片信息 bash uname -mbash-3.2$ uname -m arm64这里是自己的型号安装brew xcode-select --install xcode-select -p /bin/zsh -c “$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)” source /Users/lanren/.…

解决elementUi el-select 响应式不生效的问题

情况一,字段类型不匹配 考虑option的value值的字段类型是否和api返回的字段类型一致&#xff0c;如果一个为字符串一个为数字类型是无法匹配上的 <template> <div><el-select v-model"value" size"large"style"width: 240px"&…

STM32的HAL库开发---单通道ADC采集(DMA读取)实验

一、实验简介 正常单通道ADC采集顺序是先开启ADC采集&#xff0c;然后等待ADC转换完成&#xff0c;也就是判断EOC位置1&#xff0c;然后再读取数据寄存器的值。 如果配置了DMA功能&#xff0c;在EOC位被硬件置1后&#xff0c;自动产生DMA请求&#xff0c;然后DMA进行数据搬运…

【论文精读】VLM-AD:通过视觉-语言模型监督实现端到端自动驾驶

论文地址&#xff1a; VLM-AD: End-to-End Autonomous Driving through Vision-Language Model Supervision 摘要 人类驾驶员依赖常识推理来应对复杂多变的真实世界驾驶场景。现有的端到端&#xff08;E2E&#xff09;自动驾驶&#xff08;AD&#xff09;模型通常被优化以模仿…

mysql为啥使用B+树

MySQL 的 InnoDB 存储引擎采用 B 树作为索引结构&#xff08;而不是 B 树或其他数据结构&#xff09;&#xff0c;主要是基于 B 树在数据库场景下的独特优势。以下是 MySQL 采用 B 树的具体原因&#xff1a; 1. B 树的核心优势 &#xff08;1&#xff09;更适合范围查询 B 树…