问题背景
在selenium驱动的web自动化中,经常会碰Chrome和chromedriver版本不匹配的状况;
本篇解决的是如何自动下载与本地Chrome版本相匹配的chromedriver。
更新日志
-
增加了对Chromium 和 MS Edge 的支持
-
支持Windows, Linux, Mac OS 平台
-
增加了对chromedriver官网来源的支持(国内还是用阿里吧)
-
修改了原方案中获取浏览器版本号的方式
-
项目地址码云
大致方案(windows)
-
获取本地Chrome版本号:从注册表HKEY_CURRENT_USER\Software\Google\Chrome\BLBeacon\version中得到;
-
获取本地chromedriver版本号:找到就返回版本号,未找到就返回 0;
-
比对版本号:Chrome Version 长这样"79.0.3945.88",取前三位版本号比对,即“79.0.3945”;
-
若不一致:去淘宝镜像下载匹配的chromedriver;
-
最终实现请直接移步到本篇末尾。
细节如下(python3实现,最后会打包成 .exe程序,供双击运行)
-
获取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\'Software\Google\Chrome\BLBeacon\') _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)) -
获取chromedriver版本号
-
方式(在chromedriver.exe的目录下执行cmd命令)
G:\py\prac\chromedriver.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
-
-
建个配置文件吧,用来管理chromedriver的路径(当然你也可以写在代码里,就不用本步操作了)
-
配置文件存放路径:与该程序同级
-
内容如下:
[driver] ; absolute path of chromedriver absPath=G:\py\prac\chromedriver.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
-
-
对比版本号
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下载文件的方法 -
下载文件并解压
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\') -
显示下载进度的方法
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 \r" sys.stdout.write(s) sys.stdout.flush() if percent == 100: print(\'\') -
以线程的方式运行
import threading if __name__ == \'__main__\': threading.Thread(target=checkVersionMatch, args=(\'\')).start()
打包成 .exe程序(打包教程略过,因为运行.py文件也行)
-
双击运行cdCheck.exe 即可(注意conf.ini中absPath的值)
-
.exe下载地址
-
运行效果图
-
欢迎指正交流!!!