Python中使用Selenium自动下载适当的chromedriver

16
很遗憾,Chromedriver始终与您安装的Chrome版本有关。因此,当您使用PyInstaller在Windows上打包您的Python代码和Chromedriver到可部署的.exe文件中时,在大多数情况下它将无法工作,因为您无法在.exe文件中拥有所有Chromedriver版本。
有人知道如何从网站自动下载正确的Chromedriver吗?
如果没有,我会编写一段代码来下载zip文件并解压缩到临时文件夹。
谢谢!
8个回答

25

这是另外一种解决方案,因为 webdriver_manager 不支持。这个脚本会下载最新的 Chrome 驱动程序版本。

import requests
import wget
import zipfile
import os

# get the latest chrome driver version number
url = 'https://chromedriver.storage.googleapis.com/LATEST_RELEASE'
response = requests.get(url)
version_number = response.text

# build the donwload url
download_url = "https://chromedriver.storage.googleapis.com/" + version_number +"/chromedriver_win32.zip"

# download the zip file using the url built above
latest_driver_zip = wget.download(download_url,'chromedriver.zip')

# extract the zip file
with zipfile.ZipFile(latest_driver_zip, 'r') as zip_ref:
    zip_ref.extractall() # you can specify the destination folder path here
# delete the zip file downloaded above
os.remove(latest_driver_zip)

谢谢,如何确保它适用于Chrome浏览器版本?如果最新驱动程序是88而我的浏览器是87... - taki
4
def get_version_via_com(filename): parser = Dispatch("Scripting.FileSystemObject") version = parser.GetFileVersion(filename) return version if __name__ == "__main__": path = r"C:\Program Files\Google\Chrome\Application\chrome.exe" version_number = get_version_via_com(path)``` - supputuri
1
归档文件格式未知或已损坏。某种方式,使用wget下载归档文件不再起作用,因为它只下载了一小部分... - Cristian F.

12

以下是Python中的另一种方法 -

import chromedriver_autoinstaller
from selenium import webdriver

opt = webdriver.ChromeOptions()
opt.add_argument("--start-maximized")

chromedriver_autoinstaller.install()
driver = webdriver.Chrome(options=opt)
driver.get('https://stackoverflow.com/')

这里有更多信息:

https://pypi.org/project/chromedriver-autoinstaller/


12

截至2021年8月,这是当前状态:

chromedriver-autoinstaller

自动下载并安装支持当前已安装的 Chrome 版本的 chromedriver。此安装程序支持 Linux、MacOS 和 Windows 操作系统。

安装

pip install chromedriver-autoinstaller

用法

Just type import chromedriver_autoinstaller in the module you want to use chromedriver.

示例


from selenium import webdriver
import chromedriver_autoinstaller


chromedriver_autoinstaller.install()  # Check if the current version of chromedriver exists
                                      # and if it doesn't exist, download it automatically,
                                      # then add chromedriver to path

driver = webdriver.Chrome()
driver.get("http://www.python.org")
assert "Python" in driver.title

参考链接在这里


2
非常好,它只是有效的! - Mihai MATEI

7

1
谢谢,这对我来说是新的,不幸的是没有Py2.7支持(我知道,已经过时了,但有时旧项目无法迁移...) :) - tim

7

我有一个稍微高级一点的版本

它会检测你使用的Chrome浏览器版本,获取正确的驱动程序

def download_chromedriver():
    def get_latestversion(version):
        url = 'https://chromedriver.storage.googleapis.com/LATEST_RELEASE_' + str(version)
        response = requests.get(url)
        version_number = response.text
        return version_number
    def download(download_url, driver_binaryname, target_name):
        # download the zip file using the url built above
        latest_driver_zip = wget.download(download_url, out='./temp/chromedriver.zip')

        # extract the zip file
        with zipfile.ZipFile(latest_driver_zip, 'r') as zip_ref:
            zip_ref.extractall(path = './temp/') # you can specify the destination folder path here
        # delete the zip file downloaded above
        os.remove(latest_driver_zip)
        os.rename(driver_binaryname, target_name)
        os.chmod(target_name, 755)
    if os.name == 'nt':
        replies = os.popen(r'reg query "HKEY_CURRENT_USER\Software\Google\Chrome\BLBeacon" /v version').read()
        replies = replies.split('\n')
        for reply in replies:
            if 'version' in reply:
                reply = reply.rstrip()
                reply = reply.lstrip()
                tokens = re.split(r"\s+", reply)
                fullversion = tokens[len(tokens) - 1]
                tokens = fullversion.split('.')
                version = tokens[0]
                break
        target_name = './bin/chromedriver-win-' + version + '.exe'
        found = os.path.exists(target_name)
        if not found:
            version_number = get_latestversion(version)
            # build the donwload url
            download_url = "https://chromedriver.storage.googleapis.com/" + version_number +"/chromedriver_win32.zip"
            download(download_url, './temp/chromedriver.exe', target_name)

    elif os.name == 'posix':
        reply = os.popen(r'chromium --version').read()

        if reply != '':
            reply = reply.rstrip()
            reply = reply.lstrip()
            tokens = re.split(r"\s+", reply)
            fullversion = tokens[1]
            tokens = fullversion.split('.')
            version = tokens[0]
        else:
            reply = os.popen(r'google-chrome --version').read()
            reply = reply.rstrip()
            reply = reply.lstrip()
            tokens = re.split(r"\s+", reply)
            fullversion = tokens[2]
            tokens = fullversion.split('.')
            version = tokens[0]

        target_name = './bin/chromedriver-linux-' + version
        print('new chrome driver at ' + target_name)
        found = os.path.exists(target_name)
        if not found:
            version_number = get_latestversion(version)
            download_url = "https://chromedriver.storage.googleapis.com/" + version_number +"/chromedriver_linux64.zip"
            download(download_url, './temp/chromedriver', target_name) 
 

喜欢这个解决方案,可以通过使用reply.strip()替换reply.rstrip()和reply.lstrip()来使其稍微缩短。我没有使用目标名称的文件,而是将文件保存为chromdriver.exe,并创建了一个版本日志,以便我可以检查版本。谢谢。 - Shahin Shirazi

3

你可以使用这个

import sys
import time
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import ChromiumOptions
from webdriver_manager.chrome import ChromeDriverManager

chrome_options = ChromiumOptions()

service = Service(ChromeDriverManager().install())

driver = webdriver.Chrome(chrome_options=chrome_options, service=service)
driver.get("http://www.python.org")

time.sleep(sys.maxsize)
driver.quit()

简单明了的回答! - Jefferson Santos
最后的time.sleep(sys.maxsize)是什么意思?目标是什么? - wtfzambo
1
@wtfzambo 这是为了保持 Chrome 窗口打开。 - bikram

3
您可以使用这个解决方案。它将做两件事情:
1.在您的计算机中本地检查驱动程序版本,并将其与在线最新版本进行比较。 2.如果本地版本不匹配,则会下载最新的在线版本。
from selenium import webdriver
import requests
import zipfile
import wget
import subprocess
import os


CHROMEDRIVER_PATH =  # Insert your Chromedriver path here
CHROMEDRIVER_FOLDER = os.path.dirname(CHROMEDRIVER_PATH)
LATEST_DRIVER_URL = "https://chromedriver.storage.googleapis.com/LATEST_RELEASE"


def download_latest_version(version_number):
    print("Attempting to download latest driver online......")
    download_url = "https://chromedriver.storage.googleapis.com/" + version_number + "/chromedriver_win32.zip"
    # download zip file
    latest_driver_zip = wget.download(download_url, out=CHROMEDRIVER_FOLDER)
    # read & extract the zip file
    with zipfile.ZipFile(latest_driver_zip, 'r') as downloaded_zip:
        # You can chose the folder path to extract to below:
        downloaded_zip.extractall(path=CHROMEDRIVER_FOLDER)
    # delete the zip file downloaded above
    os.remove(latest_driver_zip)


def check_driver():
    # run cmd line to check for existing web-driver version locally
    cmd_run = subprocess.run("chromedriver --version",
                             capture_output=True,
                             text=True)
    # Extract driver version as string from terminal output
    local_driver_version = cmd_run.stdout.split()[1]
    print(f"Local driver version: {local_driver_version}")
    # check for latest chromedriver version online
    response = requests.get(LATEST_DRIVER_URL)
    online_driver_version = response.text
    print(f"Latest online chromedriver version: {online_driver_version}")
    if local_driver_version == online_driver_version:
        return True
    else:
        download_latest_version(online_driver_version)

1
这个解决方案使用默认的Python库,根据您当前本地安装的Chrome版本从互联网下载最匹配的版本。我的Linux笔记本电脑上加载了Google Chrome 97.0.4692.99版本,但是从link驱动程序中找到的最接近的版本是97.0.4692.71。如果需要,您还可以更改chrome_driver_url参数中latest的值以强制下载最新的Chrome版本。
import os
import ssl, shutil, re, platform
import zipfile
from urllib.request import urlopen
from pathlib import Path

import difflib


def chrome_driver_url(latest=False):
    def current_chrome_version():
        CHROME_RELEASE_URL = "https://sites.google.com/chromium.org/driver/downloads?authuser=0"
        try:
            response = urlopen(CHROME_RELEASE_URL,context=ssl.SSLContext(ssl.PROTOCOL_TLS)).read()
        except ssl.SSLError:
            response = urlopen(CHROME_RELEASE_URL,).read()

        downloading_version = re.findall(b"ChromeDriver \d{2,3}\.0\.\d{4}\.\d+", response)
        downloading_version = [x.decode().split(" ")[1] for x in downloading_version]
        downloading_version.sort(key=lambda x: [int(i) if i.isdigit() else i for i in x.split('.')])
        downloading_version.reverse()
        osname = platform.system()
        if osname == 'Darwin':
            installpath = "/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"
            verstr = os.popen(f"{installpath} --version").read().strip('Google Chrome ').strip()
            ver_to_download = difflib.get_close_matches(verstr, downloading_version)
            ver_to_download = ver_to_download[0]
            return ver_to_download
        elif osname == 'Windows':
            verstr = os.popen('reg query "HKEY_CURRENT_USER\Software\Google\Chrome\BLBeacon" /v version').read().strip().split(" ")
            verstr = verstr[-1]
            ver_to_download = difflib.get_close_matches(verstr, downloading_version)
            ver_to_download = ver_to_download[0]
            return ver_to_download
        elif osname == 'Linux':
            installpath = "/usr/bin/google-chrome"
            verstr = os.popen(f"{installpath} --version").read().strip('Google Chrome ').strip()
            ver_to_download = difflib.get_close_matches(verstr, downloading_version)
            ver_to_download = ver_to_download[0]
            return ver_to_download
        else:
            raise NotImplemented(f"Unknown OS '{osname}'")

    if latest:
        CHROME_RELEASE_URL = "https://sites.google.com/chromium.org/driver/downloads?authuser=0"
        try:
            response = urlopen(CHROME_RELEASE_URL, context=ssl.SSLContext(ssl.PROTOCOL_TLS)).read()
        except ssl.SSLError:
            response = urlopen(CHROME_RELEASE_URL).read()

        downloading_version = re.findall(b"ChromeDriver \d{2,3}\.0\.\d{4}\.\d+", response)[0].decode().split()[1]
    else:
        downloading_version = current_chrome_version()

    system = platform.system()
    if system == "Windows":
        url = f"https://chromedriver.storage.googleapis.com/{downloading_version}/chromedriver_win32.zip"
    elif system == "Darwin":
        # M1
        if platform.processor() == 'arm':
            url = f"https://chromedriver.storage.googleapis.com/{downloading_version}/chromedriver_mac64_m1.zip"
        else:
            url = f"https://chromedriver.storage.googleapis.com/{downloading_version}/chromedriver_mac64.zip"
    elif system == "Linux":
        url = f"https://chromedriver.storage.googleapis.com/{downloading_version}/chromedriver_linux64.zip"
    return url


def download_chrome_driver(drivers_dir):
    driver_name = "chromedriver.exe" if platform.system() == "Windows" else "chromedriver"
    if (drivers_dir / driver_name).exists():
            return
    url = chrome_driver_url()
    try:
        response = urlopen(url, context=ssl.SSLContext(ssl.PROTOCOL_TLS))  
    except ssl.SSLError:
        response = urlopen(url)  

    zip_file_path = drivers_dir / Path(url).name
    with open(zip_file_path, 'wb') as zip_file:
        while True:
            chunk = response.read(1024)
            if not chunk:
                break
            zip_file.write(chunk)

    extracted_dir = drivers_dir / zip_file_path.stem
    with zipfile.ZipFile(zip_file_path, "r") as zip_file:
        zip_file.extractall(extracted_dir)
    os.remove(zip_file_path)

    driver_path = drivers_dir / driver_name
    try:
        (extracted_dir / driver_name).rename(driver_path)

    except FileExistsError:
        (extracted_dir / driver_name).replace(driver_path)

    shutil.rmtree(extracted_dir)
    os.chmod(driver_path, 0o755)

if __name__ == "__main__":
    chrome_driver_location = Path("chrome_driver")
    chrome_driver_location.mkdir(exist_ok=True)
    download_chrome_driver(chrome_driver_location)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接