当前位置: 首页 > article >正文

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

        在上一篇文章中,我们介绍了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:

'//*[@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 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模块即可

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_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.kler.cn/a/556847.html

相关文章:

  • 城电科技|可展开光伏花 绽放绿色 点亮未来
  • JavaScript 中,数据类型 有哪些?(复习/面试)
  • JVM系列--虚拟机类加载机制
  • TSMaster【第四篇:目击之术——总线测量窗口精解】
  • MATLAB拟合算法:如何使用 MATLAB 进行多组数据的高斯拟合分析
  • 【Kubernets】Kubernets资源类型Deployment详细介绍
  • 图数据库Neo4j面试内容整理-深度优先搜索(DFS)和广度优先搜索(BFS)
  • C语言03
  • 可编辑112页PPT | DeepSeek行业应用实践报告
  • 【TOT】Tree-of-Thought Prompting
  • day16_推荐系统和总结
  • ARM64 Trust Firmware [四]
  • 开启开源新时代:DeepSeek引领人工智能技术开放化
  • 科普:你的笔记本电脑中有三个IP:127.0.0.1、无线网 IP 和局域网 IP;两个域名:localhost和host.docker.internal
  • 电力通信物联网应用,国密网关守护电力数据安全
  • Java 表达式、语句和块
  • nginx配置:nginx.conf配置文件
  • spring中事务为什么会回滚?什么原理?
  • Vue 和 React 响应式的区别
  • 植物大战僵尸杂交版v3.2.1最新版本(附下载链接)