小小明-代码实体

小小明-代码实体

原本selenium4已经更新了自动获取驱动的方案,但目前最大只能获取到115版本,而115版本还能够使用也只是因为114版本能够驱动谷歌游览器。
如今,我的谷歌游览器已经到了119版本,以前编写的自动更新驱动的方案全部报废。
自动更新Selenium驱动chromedriver:https://blog.csdn.net/as604049322/article/details/125540557

具体情况,可查看https://chromedriver.chromium.org/downloads

目前115以上版本的谷歌游览器基本只能手动升级驱动,但经过我潜心对上述json的研究,已经整理出了一套自动升级方案,下面直接给出完整代码:

# 博客地址:https://blog.csdn.net/as604049322
__author__ = '小小明-代码实体'
__date__ = '2023/11/1'

import os
import platform
import re
import subprocess
import sys
import time
import winreg
import zipfile

import requests
from selenium import webdriver
from selenium.common import WebDriverException
from tqdm import tqdm


def linux_browser_apps_to_cmd() -> str:
    """获取以下类似的命令的结果:
        google-chrome --version || google-chrome-stable --version
    """
    apps = ("google-chrome", "google-chrome-stable",
            "google-chrome-beta", "google-chrome-dev")
    ignore_errors_cmd_part = " 2>/dev/null" if os.getenv("WDM_LOG_LEVEL") == "0" else ""
    return " || ".join(f"{i} --version{ignore_errors_cmd_part}" for i in apps)


def window_get_browser_version():
    """代码作者:小小明-代码实体 xxmdmst.blog.csdn.net"""
    try:
        key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
                             r"SOFTWARE\Google\Chrome\BLBeacon")
        version, _ = winreg.QueryValueEx(key, "version")
        winreg.CloseKey(key)
        return version
    except:
        pass
    try:
        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,
                             r"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Google Chrome")
        version, _ = winreg.QueryValueEx(key, "version")
        winreg.CloseKey(key)
        return version
    except:
        pass


def read_version_from_cmd(cmd):
    with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL,
                          stdin=subprocess.DEVNULL, shell=True) as stream:
        stdout = stream.communicate()[0].decode()
    return stdout


def get_browser_version_from_os():
    pl = sys.platform
    try:
        if pl == "linux" or pl == "linux2":
            cmd = linux_browser_apps_to_cmd()
            version = read_version_from_cmd(cmd)
        elif pl == "darwin":
            cmd = r"/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --version"
            version = read_version_from_cmd(cmd)
        elif pl == "win32":
            version = window_get_browser_version()
        else:
            return None
        version = re.search(r"\d+\.\d+\.\d+", version)
        return version.group(0) if version else None
    except Exception as e:
        return None


def os_type():
    pl = sys.platform
    architecture = platform.machine().lower()
    if pl == "darwin":
        if architecture == "x86_64":
            architecture = "x64"
        return f"mac_{architecture}"
    pl = re.search("[a-z]+", pl).group(0)
    architecture = 64 if architecture.endswith("64") else 32
    return f"{pl}{architecture}"


def get_chromedriver_url(version):
    chrome_url = "https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json"
    res = requests.get(chrome_url)
    os_type_str = os_type()
    for obj in reversed(res.json()["versions"]):
        if obj["version"].startswith(version):
            for downloads in obj["downloads"]["chromedriver"]:
                if downloads["platform"] == os_type_str:
                    return obj["version"], downloads["url"]
            break


def show_download_progress(response, _bytes_threshold=100):
    """代码作者:小小明-代码实体 xxmdmst.blog.csdn.net"""
    total = int(response.headers.get("Content-Length", 0))
    if total > _bytes_threshold:
        content = bytearray()
        progress_bar = tqdm(desc="[WDM] - Downloading", total=total,
                            unit_scale=True, unit_divisor=1024, unit="B")
        for chunk in response.iter_content(chunk_size=8192):
            if chunk:
                progress_bar.update(len(chunk))
                content.extend(chunk)
        progress_bar.close()
        response._content = content


def install_new_driver():
    """代码作者:小小明-代码实体 xxmdmst.blog.csdn.net"""
    version = get_browser_version_from_os()
    print(f"谷歌游览器版本:{version}")
    driver_version, url = get_chromedriver_url(version)
    filename = url[url.rfind("/") + 1:]
    filename, ext = os.path.splitext(filename)
    file = f"{filename}_v{driver_version}{ext}"
    if os.path.exists(file):
        print(file, "已存在,跳过下载~")
    else:
        resp = requests.get(url, stream=True)
        show_download_progress(resp)
        with open(file, 'wb') as f:
            f.write(resp._content)
    with zipfile.ZipFile(file) as zf:
        for name in zf.namelist():
            if name.endswith("chromedriver.exe"):
                zf.extract(name, ".")
                print(name, "已解压到当前文件夹~")
                break
    if name != os.path.basename(name):
        if os.path.exists(os.path.basename(name)):
            os.remove(os.path.basename(name))
        os.rename(name, os.path.basename(name))
        print("已从", name, "移动到", os.path.basename(name))
    return os.path.abspath(os.path.basename(name))


def getChromeDriver(options=None):
    """代码作者:小小明-代码实体 xxmdmst.blog.csdn.net"""
    if not os.path.exists("chromedriver.exe") and get_browser_version_from_os() > "114":
        # 如果chromedriver不存在并且版本大于114直接升级,否则可以使用selenium4自动获取driver的功能
        install_new_driver()
    try:
        driver = webdriver.Chrome(options=options)
        return driver
    except WebDriverException as e:
        print(e)
        install_new_driver()
    driver = webdriver.Chrome(options=options)
    return driver


if __name__ == '__main__':
    options = webdriver.ChromeOptions()
    options.add_experimental_option(
        'excludeSwitches', ['enable-logging', 'enable-automation'])
    # driver = webdriver.Chrome(options=options)
    driver = getChromeDriver(options)
    driver.get("https://www.baidu.com/")
    time.sleep(5)

以上代码可以以一个工具函数的形式单独存储。

11-02 09:49