用 selenium 做过自动化的都知道由于谷歌游览器经常自动更新导致 selenium 驱动失效需要重新下载解压替换当然我们也可以禁用浏览器的自动更新但这个替换动作手动去做的话又十分麻烦。所以最好是在谷歌浏览器和 chromedriver 版本不匹配时自动下载匹配的 chromedriver.exe 就好了。谷歌浏览器版本获取selenium我们可以先随意找一个 chromedriver然后基于这个 chromedriver 使用 selenium 去尝试初始化 driver如果版本不匹配的话会有如下报错提示然后我们就可以获取到当前谷歌浏览器的版本信息了。from selenium import webdriver try: driver webdriver.Chrome(executable_path./driver/chromedriver.exe) except Exception as e: print(str(e))Message: session not created: This version of ChromeDriver only supports Chrome version 140 Current browser version is 120.0.6099.130 with binary path C:\Program Files\Google\Chrome\Application\chrome.exechrome_version推荐上面的方法很直接唯一的缺点是我必须要先有一个 chromedriver假如我还没有现成的 chromedriver 但又想获取浏览器版本就不方便了。不过我们可以直接使用 chrome-version 来获取谷歌浏览器版本。pip install chrome-version使用时直接调用 get_chrome_version() 函数即可。import chrome_version version chrome_version.get_chrome_version() print(version) # 120.0.6099.130其源码也很简单针对 Windows 系统它从浏览器安装后的注册表中获取 DisplayVersion 版本并正则提取。HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Google Chrome DisplayName REG_SZ Google Chrome UninstallString REG_SZ C:\Program Files\Google\Chrome\Application\120.0.6099.130\Installer\setup.exe --uninstall --channelstable --system-level --verbose-logging InstallLocation REG_SZ C:\Program Files\Google\Chrome\Application DisplayIcon REG_SZ C:\Program Files\Google\Chrome\Application\chrome.exe,0 NoModify REG_DWORD 0x1 NoRepair REG_DWORD 0x1 Publisher REG_SZ Google LLC Version REG_SZ 120.0.6099.130 DisplayVersion REG_SZ 120.0.6099.130 InstallDate REG_SZ 20231222 VersionMajor REG_DWORD 0x17d3 VersionMinor REG_DWORD 0x82playwrightplaywright 也可以在不使用 chromedriver 的情况下获取浏览器的版本信息。from playwright.sync_api import sync_playwright with sync_playwright() as p: browser p.chromium.launch(executable_pathC:\Program Files\Google\Chrome\Application\chrome.exe) print(browser.version) # 120.0.6099.130DrissionPageDrissionPage 也可以在不使用 chromedriver 的情况下获取到浏览器的版本信息。from DrissionPage import ChromiumPage, ChromiumOptions co ChromiumOptions() co.headless() page ChromiumPage(co) print(page.browser_version) # Chrome/120.0.6099.130匹配版本最接近的 chromedriver一般来说谷歌浏览器的版本和 chromedriver 的版本并不完全是一对一的关系。浏览器先发布后续才更新的 chromedriver 版本一个版本的 chromedriver 可能支持多个浏览器版本。比如我浏览器版本是 120.0.6099.130但是并没有这个版本的 chromedriver。所以查找时我们可以查找主版本与其一致但子版本与之最接近的版本作为对应的 chromedriver 的版本。import re import itertools import requests import chrome_version def get_chromedriver_version(browser_version): res requests.get(https://registry.npmmirror.com/-/binary/chrome-for-testing/) results res.json() # 筛选满足要求的 version versions [obj[name][:-1] for obj in results if re.match(\d, obj[name]) and obj[name].count(.) 3] # 先排序将相邻版本的数据放在一块 versions sorted(versions) versions {key: list(versions_split) for key, versions_split in itertools.groupby(versions, keylambda x: x[:x.rfind(.)])} # 取前3个版本作为必须匹配的主版本 main_version browser_version[:browser_version.rfind(.)] sub_version browser_version[browser_version.rfind(.) 1:] for version, version_list in versions.items(): if main_version version: # 在主版本完全匹配的情况下匹配最接近的子版本并返回 diff_dict {abs(int(sub_version) - int(v[v.rfind(.) 1:])): v for v in version_list} # print(diff_dict) min_diff min(diff_dict.keys()) return diff_dict[min_diff] return if __name__ __main__: # browser_version 120.0.6099.130 browser_version chrome_version.get_chrome_version() print(fbrowser_version: {browser_version}) chromedriver_version get_chromedriver_version(browser_version) print(fchromedriver_version: {chromedriver_version})browser_version: 120.0.6099.130 chromedriver_version: 120.0.6099.109下载对应版本的 chromedriver查到对应的版本后我们就可以从镜像地址 https://registry.npmmirror.com/binary.html?pathchrome-for-testing 下载 chromedriver 了。由于下载的文件是 zip 形式的压缩包所以还需要我们提取到指定的目录。import os import re import itertools import zipfile import shutil import requests import chrome_version def get_chromedriver_version(browser_version): res requests.get(https://registry.npmmirror.com/-/binary/chrome-for-testing/) results res.json() # 筛选满足要求的 version versions [obj[name][:-1] for obj in results if re.match(\d, obj[name]) and obj[name].count(.) 3] # 先排序将相邻版本的数据放在一块 versions sorted(versions) versions {key: list(versions_split) for key, versions_split in itertools.groupby(versions, keylambda x: x[:x.rfind(.)])} # 取前3个版本作为必须匹配的主版本 main_version browser_version[:browser_version.rfind(.)] sub_version browser_version[browser_version.rfind(.) 1:] for version, version_list in versions.items(): if main_version version: # 在主版本完全匹配的情况下匹配最接近的子版本并返回 diff_dict {abs(int(sub_version) - int(v[v.rfind(.) 1:])): v for v in version_list} # print(diff_dict) min_diff min(diff_dict.keys()) return diff_dict[min_diff] return def download_chromedriver(chromedriver_version, output_dir): try: os.makedirs(output_dir, exist_okTrue) if os.path.exists(os.path.join(output_dir, chromedriver.exe)): os.remove(os.path.join(output_dir, chromedriver.exe)) file fchromedriver-win64.zip url fhttps://cdn.npmmirror.com/binaries/chrome-for-testing/{chromedriver_version}/win64/{file} res requests.get(url) with open(file, wb) as f: f.write(res.content) with zipfile.ZipFile(file, r) as zipf: zipf.extract(chromedriver-win64/chromedriver.exe, output_dir) shutil.move(os.path.join(output_dir, chromedriver-win64/chromedriver.exe), output_dir) shutil.rmtree(os.path.join(output_dir, chromedriver-win64)) return True except Exception as e: print(f文件下载和提取失败{str(e)}) return False if __name__ __main__: # browser_version 120.0.6099.130 browser_version chrome_version.get_chrome_version() print(fbrowser_version: {browser_version}) chromedriver_version get_chromedriver_version(browser_version) print(fchromedriver_version: {chromedriver_version}) output_dir ./driver download_chromedriver(chromedriver_version, output_dir)校验下载的 chromedriver我们可以尝试使用新更新的 chromedriver.exe 来打开浏览器并访问网页看是否还会报错。import time from selenium import webdriver driver webdriver.Chrome(executable_path./driver/chromedriver.exe) try: driver.get(https://www.baidu.com/) time.sleep(10) except Exception as e: print(str(e)) finally: driver.quit()发现能正常打开百度页面说明当前的 chromedriver 版本是和浏览器匹配的。注意校验结束后记得一定要 driver.quit() 退出 chromedriver否则可能会出现进程残留导致后续无法删除和替换 chromedriver.exe 文件。文件下载和提取失败[WinError 5] 拒绝访问。: ./driver\\chromedriver.exe
Python 之自动下载更新 selenium 驱动 chromedriver
用 selenium 做过自动化的都知道由于谷歌游览器经常自动更新导致 selenium 驱动失效需要重新下载解压替换当然我们也可以禁用浏览器的自动更新但这个替换动作手动去做的话又十分麻烦。所以最好是在谷歌浏览器和 chromedriver 版本不匹配时自动下载匹配的 chromedriver.exe 就好了。谷歌浏览器版本获取selenium我们可以先随意找一个 chromedriver然后基于这个 chromedriver 使用 selenium 去尝试初始化 driver如果版本不匹配的话会有如下报错提示然后我们就可以获取到当前谷歌浏览器的版本信息了。from selenium import webdriver try: driver webdriver.Chrome(executable_path./driver/chromedriver.exe) except Exception as e: print(str(e))Message: session not created: This version of ChromeDriver only supports Chrome version 140 Current browser version is 120.0.6099.130 with binary path C:\Program Files\Google\Chrome\Application\chrome.exechrome_version推荐上面的方法很直接唯一的缺点是我必须要先有一个 chromedriver假如我还没有现成的 chromedriver 但又想获取浏览器版本就不方便了。不过我们可以直接使用 chrome-version 来获取谷歌浏览器版本。pip install chrome-version使用时直接调用 get_chrome_version() 函数即可。import chrome_version version chrome_version.get_chrome_version() print(version) # 120.0.6099.130其源码也很简单针对 Windows 系统它从浏览器安装后的注册表中获取 DisplayVersion 版本并正则提取。HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Google Chrome DisplayName REG_SZ Google Chrome UninstallString REG_SZ C:\Program Files\Google\Chrome\Application\120.0.6099.130\Installer\setup.exe --uninstall --channelstable --system-level --verbose-logging InstallLocation REG_SZ C:\Program Files\Google\Chrome\Application DisplayIcon REG_SZ C:\Program Files\Google\Chrome\Application\chrome.exe,0 NoModify REG_DWORD 0x1 NoRepair REG_DWORD 0x1 Publisher REG_SZ Google LLC Version REG_SZ 120.0.6099.130 DisplayVersion REG_SZ 120.0.6099.130 InstallDate REG_SZ 20231222 VersionMajor REG_DWORD 0x17d3 VersionMinor REG_DWORD 0x82playwrightplaywright 也可以在不使用 chromedriver 的情况下获取浏览器的版本信息。from playwright.sync_api import sync_playwright with sync_playwright() as p: browser p.chromium.launch(executable_pathC:\Program Files\Google\Chrome\Application\chrome.exe) print(browser.version) # 120.0.6099.130DrissionPageDrissionPage 也可以在不使用 chromedriver 的情况下获取到浏览器的版本信息。from DrissionPage import ChromiumPage, ChromiumOptions co ChromiumOptions() co.headless() page ChromiumPage(co) print(page.browser_version) # Chrome/120.0.6099.130匹配版本最接近的 chromedriver一般来说谷歌浏览器的版本和 chromedriver 的版本并不完全是一对一的关系。浏览器先发布后续才更新的 chromedriver 版本一个版本的 chromedriver 可能支持多个浏览器版本。比如我浏览器版本是 120.0.6099.130但是并没有这个版本的 chromedriver。所以查找时我们可以查找主版本与其一致但子版本与之最接近的版本作为对应的 chromedriver 的版本。import re import itertools import requests import chrome_version def get_chromedriver_version(browser_version): res requests.get(https://registry.npmmirror.com/-/binary/chrome-for-testing/) results res.json() # 筛选满足要求的 version versions [obj[name][:-1] for obj in results if re.match(\d, obj[name]) and obj[name].count(.) 3] # 先排序将相邻版本的数据放在一块 versions sorted(versions) versions {key: list(versions_split) for key, versions_split in itertools.groupby(versions, keylambda x: x[:x.rfind(.)])} # 取前3个版本作为必须匹配的主版本 main_version browser_version[:browser_version.rfind(.)] sub_version browser_version[browser_version.rfind(.) 1:] for version, version_list in versions.items(): if main_version version: # 在主版本完全匹配的情况下匹配最接近的子版本并返回 diff_dict {abs(int(sub_version) - int(v[v.rfind(.) 1:])): v for v in version_list} # print(diff_dict) min_diff min(diff_dict.keys()) return diff_dict[min_diff] return if __name__ __main__: # browser_version 120.0.6099.130 browser_version chrome_version.get_chrome_version() print(fbrowser_version: {browser_version}) chromedriver_version get_chromedriver_version(browser_version) print(fchromedriver_version: {chromedriver_version})browser_version: 120.0.6099.130 chromedriver_version: 120.0.6099.109下载对应版本的 chromedriver查到对应的版本后我们就可以从镜像地址 https://registry.npmmirror.com/binary.html?pathchrome-for-testing 下载 chromedriver 了。由于下载的文件是 zip 形式的压缩包所以还需要我们提取到指定的目录。import os import re import itertools import zipfile import shutil import requests import chrome_version def get_chromedriver_version(browser_version): res requests.get(https://registry.npmmirror.com/-/binary/chrome-for-testing/) results res.json() # 筛选满足要求的 version versions [obj[name][:-1] for obj in results if re.match(\d, obj[name]) and obj[name].count(.) 3] # 先排序将相邻版本的数据放在一块 versions sorted(versions) versions {key: list(versions_split) for key, versions_split in itertools.groupby(versions, keylambda x: x[:x.rfind(.)])} # 取前3个版本作为必须匹配的主版本 main_version browser_version[:browser_version.rfind(.)] sub_version browser_version[browser_version.rfind(.) 1:] for version, version_list in versions.items(): if main_version version: # 在主版本完全匹配的情况下匹配最接近的子版本并返回 diff_dict {abs(int(sub_version) - int(v[v.rfind(.) 1:])): v for v in version_list} # print(diff_dict) min_diff min(diff_dict.keys()) return diff_dict[min_diff] return def download_chromedriver(chromedriver_version, output_dir): try: os.makedirs(output_dir, exist_okTrue) if os.path.exists(os.path.join(output_dir, chromedriver.exe)): os.remove(os.path.join(output_dir, chromedriver.exe)) file fchromedriver-win64.zip url fhttps://cdn.npmmirror.com/binaries/chrome-for-testing/{chromedriver_version}/win64/{file} res requests.get(url) with open(file, wb) as f: f.write(res.content) with zipfile.ZipFile(file, r) as zipf: zipf.extract(chromedriver-win64/chromedriver.exe, output_dir) shutil.move(os.path.join(output_dir, chromedriver-win64/chromedriver.exe), output_dir) shutil.rmtree(os.path.join(output_dir, chromedriver-win64)) return True except Exception as e: print(f文件下载和提取失败{str(e)}) return False if __name__ __main__: # browser_version 120.0.6099.130 browser_version chrome_version.get_chrome_version() print(fbrowser_version: {browser_version}) chromedriver_version get_chromedriver_version(browser_version) print(fchromedriver_version: {chromedriver_version}) output_dir ./driver download_chromedriver(chromedriver_version, output_dir)校验下载的 chromedriver我们可以尝试使用新更新的 chromedriver.exe 来打开浏览器并访问网页看是否还会报错。import time from selenium import webdriver driver webdriver.Chrome(executable_path./driver/chromedriver.exe) try: driver.get(https://www.baidu.com/) time.sleep(10) except Exception as e: print(str(e)) finally: driver.quit()发现能正常打开百度页面说明当前的 chromedriver 版本是和浏览器匹配的。注意校验结束后记得一定要 driver.quit() 退出 chromedriver否则可能会出现进程残留导致后续无法删除和替换 chromedriver.exe 文件。文件下载和提取失败[WinError 5] 拒绝访问。: ./driver\\chromedriver.exe