自动获取谷歌版本,并自动下载对应版本的chromedriver.exe

前言

问题:google浏览器频繁更新自动升级、同事使用的Google浏览器版本不一致,需要手动去下载驱动,非常的无语。本着碰到问题就解决问题的心态,写一个自动下载驱动的方法,后来发现了一个驱动管理包非常实用,分享给大家。
当前方法只适配了Windows上的驱动,其它系统和浏览器可以自己修改配置信息适配一下。废话不多说直接上代码。

依赖包安装

python -m pip install -i https://mirrors.aliyun.com/pypi/simple webdriver-manager==4.0.1

代码内容

#  _*_ coding:utf-8 _*_
import json
import os
import re
import subprocess
import logging as log
from webdriver_manager.chrome import ChromeDriverManager
from webdriver_manager.firefox import GeckoDriverManager
from webdriver_manager.microsoft import EdgeChromiumDriverManager


def check_dir_exist(dirname: str = None) -> str:
    """检查计算机用户根目录中是否存在目录,不存在就创建,未指定则查询"""
    user_dir = os.path.expanduser("~")
    if dirname is None:
        return user_dir
    cache_dir = os.path.join(user_dir, dirname)
    if not os.path.isdir(cache_dir):
        os.makedirs(cache_dir, exist_ok=True)
    return cache_dir


def get_driver_path(driver_name: str = 'chromedriver') -> str:
    """
    获取驱动路径,如果没有、版本与安装的浏览器版本不一致则自动更新下载,有的话获取缓存的驱动
    :param driver_name: 浏览器名称
        chromedriver        谷歌驱动
        edgedriver          edge 驱动
        geckodriver         火狐驱动
    :return: 浏览器驱动路径
    """
    driver_names = {
        'chromedriver': {
            'query': r'reg query "HKEY_CURRENT_USER\Software\Google\Chrome\BLBeacon" /v version',
            'class': ChromeDriverManager,
            'name': 'chromedriver.exe'
        },
        'edgedriver': {
            'query': r'reg query "HKEY_CURRENT_USER\Software\Microsoft\Edge\BLBeacon" /v version',
            'class': EdgeChromiumDriverManager,
            'name': 'msedgedriver.exe'
        },
        'geckodriver': {
            'query': r'reg query "HKEY_CURRENT_USER\SOFTWARE\Mozilla\Mozilla Firefox" /v CurrentVersion',
            'class': GeckoDriverManager,
            'name': 'geckodriver.exe'
        },
    }.get(driver_name)
    if driver_names:
        local_verinfo = subprocess.check_output(driver_names['query'], shell=True).decode()
        browser_verinfo = re.compile(r' ([0-9]+)\.[0-9]+').findall(local_verinfo)
        if not browser_verinfo:
            log.error(f'获取本地 {driver_name} 浏览器版本失败:{local_verinfo}')
        # 获取本地浏览器驱动缓存路径
        drivers_path = os.path.join(check_dir_exist(), '.wdm/drivers.json')
        ver_path = ''
        ver_path_key = ''
        driver_regex = re.compile(driver_name + r'.*_for_([0-9]+)\.')
        if os.path.isfile(drivers_path):
            with open(drivers_path, 'r') as file:
                data = json.load(file)
            for i in [k for k in data]:
                cache_ver = driver_regex.findall(i)
                if cache_ver:
                    if len(browser_verinfo) == 1 and cache_ver[0] == browser_verinfo[0]:
                        ver_path = data[i]['binary_path']
                        ver_path_key = i
        if not ver_path:
            log.info(f'未找到本地 {driver_name} 驱动,开始下载,时间可能会比较长,请稍等......')
            ver_path = driver_names['class']().install()
            log.info(f'驱动下载完成,驱动路径:{ver_path}')
        # 检查是不是正确的驱动路径,有的 google 驱动版本自动下载后路径是错误的,这里重新拼接一下
        if ver_path and not ver_path.endswith(driver_names['name']):
            log.warning(f'不是正确的驱动路径,重新拼接地址。错误路径:{ver_path}')
            ver_path_new = os.path.realpath(os.path.join(os.path.dirname(ver_path), driver_names['name']))
            with open(drivers_path, "r") as f:
                data = json.load(f)
            with open(drivers_path, "w+", encoding='utf-8') as f:
                for i in [k for k in data]:
                    cache_ver = driver_regex.findall(i)
                    if cache_ver:
                        if len(browser_verinfo) == 1 and cache_ver[0] == browser_verinfo[0]:
                            ver_path_key = i
                data[ver_path_key]['binary_path'] = ver_path_new
                json.dump(data, f, indent=4)
            with open(drivers_path, 'r') as f_new:
                data_new = json.load(f_new)
            ver_path = data_new[ver_path_key]['binary_path']
            log.info(f'驱动路径重新初始化成功:{ver_path}')
        msg = '谷歌驱动下载地址:https://googlechromelabs.github.io/chrome-for-testing/#stable \n' + \
              'edge驱动下载地址:https://msedgedriver.azureedge.net \n' + \
              '火狐驱动下载地址::https://github.com/mozilla/geckodriver/releases'
        if not ver_path:
            log.error(msg)
            raise ValueError('驱动更新失败,请检查\n' + msg)
        return ver_path
    else:
        raise ValueError(f'{driver_name} 驱动暂不支持')


if __name__ == '__main__':
    print(get_driver_path())

驱动自动下载逻辑说明

  1. 本地不存在驱动,自动获取当前安装的浏览器(浏览器存在)版本,并下载跟本地浏览器版本匹配的浏览器驱动,例如:chrome_driver。
  2. 本地存在驱动(或多个),优先获取本地已下载的驱动版本和本地浏览器版本进行比较,不一致则会重新下载最新的驱动。
  3. 本地存在驱动(或多个),优先获取本地已下载的驱动版本和本地浏览器版本进行比较,版本一致且多个同一版本的驱动则取本地最新下载的驱动路径。
  4. 优先取本地驱动的原因:例如重复调用google驱动下载类影响启动浏览器的效率,且容易封ip(亲测),最重要的是太慢了。
  5. 只适配了window,其他平台未适配,如有需要欢迎留言;如果查询本地浏览器版本的bat命令无效,则需要自己改一下query的内容。
Logo

更多推荐