获取Chrome版本并下载匹配的chromedriver

问题背景

在selenium驱动的web自动化中,经常会碰Chrome和chromedriver版本不匹配的状况;
本篇解决的是如何自动下载与本地Chrome版本相匹配的chromedriver。

更新日志

  1. 增加了对Chromium 和 MS Edge 的支持

  2. 支持Windows, Linux, Mac OS 平台

  3. 增加了对chromedriver官网来源的支持(国内还是用阿里吧)

  4. 修改了原方案中获取浏览器版本号的方式

  5. 项目地址码云

大致方案(windows)

  1. 获取本地Chrome版本号:从注册表HKEY_CURRENT_USERSoftwareGoogleChromeBLBeaconversion中得到;

  2. 获取本地chromedriver版本号:找到就返回版本号,未找到就返回 0;

  3. 比对版本号:Chrome Version 长这样"79.0.3945.88",取前三位版本号比对,即“79.0.3945”;

  4. 若不一致:去淘宝镜像下载匹配的chromedriver;

  5. 最终实现请直接移步到本篇末尾

细节如下(python3实现,最后会打包成 .exe程序,供双击运行)

  1. 获取Chrome版本号

    import winreg  # 和注册表交互
    import re  # 正则模块
     
    version_re = re.compile(r'^[1-9]d*.d*.d*')  # 匹配前3位版本号的正则表达式
     
    def getChromeVersion():
        try:
        # 从注册表中获得版本号
            key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'SoftwareGoogleChromeBLBeacon')
    
            _v, type = winreg.QueryValueEx(key, 'version')
    
            print('Current Chrome Version: {}'.format(_v)) # 这步打印会在命令行窗口显示
    
            return version_re.findall(_v)[0]  # 返回前3位版本号
    
        except WindowsError as e:
            print('check Chrome failed:{}'.format(e))
    
  2. 获取chromedriver版本号

    • 方式(在chromedriver.exe的目录下执行cmd命令)

      G:pypracchromedriver.exe --version
      prac 79.0.3945.36 (3582db32b33893869b8c1339e8f4d9ed1816f143-refs/branch-heads/3945@{#614})
      
    • 代码实现如下

      import subprocess  # 用于执行cmd命令
      
      def getDriverVersion(absPath):
         """
         @param absPath: chromedriver.exe的绝对路径
         """
         cmd = r'{} --version'.format(absPath)  # 拼接成cmd命令
         
         try:
             # 执行cmd命令并接收命令回显
             out, err = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
             out = out.decode('utf-8')
             	
             _v = out.split(' ')[1] # 拆分回显字符串,获取版本号
             print('Current chromedriver Version:{}'.format(_v))
      
             return version_re.findall(_v)[0]
         except IndexError as e:
             print('check chromedriver failed:{}'.format(e))
             return 0
      
  3. 建个配置文件吧,用来管理chromedriver的路径(当然你也可以写在代码里,就不用本步操作了)

    • 配置文件存放路径:与该程序同级

    • 内容如下:

      [driver]
      ; absolute path of chromedriver
      absPath=G:pypracchromedriver.exe
      
      ; DO NOT modify the url
      url=http://npm.taobao.org/mirrors/chromedriver/
      
    • 定义读取上述文件的方法

      from configparser import RawConfigParser  # 用于解析.ini格式的配置文件
      
      def get_ini(file):
          _ini = RawConfigParser()
          _ini.read(file, encoding='utf-8')
          return _ini
      
  4. 对比版本号

    import os
     
    def checkVersionMatch():
        # 读取conf.ini中的配置项
        conf = get_ini('conf.ini')
        absPath = conf.get('driver', 'absPath')
    
        print('Chrome version compares with chromedriver version')
        c_v = getChromeVersion()
        d_v = getDriverVersion(absPath)
    
        if c_v == d_v:
            # 若匹配,在命令行窗口提示下面的信息
            input('Chrome and chromedriver are matched. Press Enter to exit.')
        else:
            # 若不匹配,走下面的流程去下载chromedriver
            _v = c_v
    
            url = conf.get('driver', 'url') # 从conf.ini中获取淘宝镜像url
    
            save_d = os.path.dirname(absPath) # 下载文件的保存路径,与chromedriver同级
    
            downLoadDriver(_v, url, save_d) # call下载文件的方法
    
  5. 下载文件并解压

    import urllib.request  	# 发送http请求
    import urllib.parse  	# 拼接url
    import zipfile  		# 操作.zip文件
    
    def downLoadDriver(__v, url, save_d):
        # 访问淘宝镜像首页
        rep = urllib.request.urlopen(url).read().decode('utf-8')
        # '<a href="/mirrors/chromedriver/84.0.4147.30/">84.0.4147.30/</a>'
        directory = re.compile(r'>(d.*?/)</a>').findall(rep)  # 匹配文件夹(版本号)
     	
        # 获取期望的文件夹(版本号)
        match_list = []
        for i in directory:
            v = version_re.findall(i)[0]
            if __v == v:
                match_list.append(i)
          
        # http://npm.taobao.org/mirrors/chromedriver/83.0.4103.39/chromedriver_win32.zip
        dirUrl = urllib.parse.urljoin(url, match_list[-1])
    
        downUrl = urllib.parse.urljoin(dirUrl, 'chromedriver_win32.zip') # 拼接出下载路径
        print('will download {}'.format(downUrl))
    
        # 指定下载的文件名和保存位置
        file = os.path.join(save_d, os.path.basename(downUrl))
        print('will saved in {}'.format(file))
    
        # 开始下载,并显示下载进度(progressFunc)
        urllib.request.urlretrieve(downUrl, file, progressFunc)
    
        # 下载完成后解压
        zFile = zipfile.ZipFile(file, 'r')
        for fileM in zFile.namelist():
            zFile.extract(fileM, os.path.dirname(file))
        zFile.close()
     	
        input('Complete, press Enter to exit')
    
  6. 显示下载进度的方法

    import sys
     
    def progressFunc(blocknum, blocksize, totalsize):
        '''作回调函数用
        @blocknum: 已经下载的数据块
        @blocksize: 数据块的大小
        @totalsize: 远程文件的大小
        '''
        percent = 100.0 * blocknum * blocksize / totalsize
    
        if percent > 100:
            percent = 100
        downsize = blocknum * blocksize
    
        if downsize >= totalsize:
            downsize = totalsize
    
        s = "%.2f%%" % (percent) + "====>" + "%.2f" % (downsize / 1024 / 1024) + "M/" + "%.2f" % (totalsize / 1024 / 1024) + "M 
    "
        sys.stdout.write(s)
        sys.stdout.flush()
    
        if percent == 100:
            print('')
    
  7. 以线程的方式运行

    import threading
     
    if __name__ == '__main__':
        threading.Thread(target=checkVersionMatch, args=('')).start()
    

打包成 .exe程序(打包教程略过,因为运行.py文件也行)

  • 双击运行cdCheck.exe 即可(注意conf.ini中absPath的值)

    avatar

  • .exe下载地址

  • 运行效果图

    avatar

  • 欢迎指正交流!!!

原文地址:https://www.cnblogs.com/z417/p/13785734.html