🎃

【Python】seleniumで使うChromeDriverを自動更新

2023/10/01に公開

今回は毎回更新されるchromeに合わせたドライバーを自動でしてくれるコードを解説していきます。
Zennに投稿するようなので解説になります。
環境によって変わると思うので先ずは環境から

環境

  • Windows 11
  • selenium 4.13.0
  • Python 3.11.5
  • Chrome 115以降

必要な情報はこれくらいですかね。
特にSeleniumはバージョンによって起動の仕方とか違うので気を付けてください。
chromeは115より前のバージョンだとダウンロード先が変わるので注意してください。
一応以前のバージョンのやつもGithub内に入れておきます。(previous_version.py)
確かChatGPT使いながら作った気がします。
今回のもChatGPT使います。
結局大元はできるのですがエラーばかりなのでかなり手直ししました😅

動きの確認

動きとしては以下のようになります。
webdriverの起動

うまくいけば終了

webdriverの起動の際errorが出た場合

  1. fileがないパターン
  2. バージョンが違うパターン

とりあえずはこの二つですね。
1.の場合はとりあえずChromeのバージョンが知りたいので最新版のdriverをダウンロード
あとは起動して繰り返します。
2.の場合エラーメッセージから必要なバージョンを取得しそのバージョンをダウンロード

コーディング

まず、起動の確認から

起動の確認

ここは起動したらtrue、失敗したらエラーを返すようにしました。
返す型が違うくてもいいのは動的型付けのいいところですかね。
Seleniumのバージョンによってこの起動部分は変わるので以前のバージョンを使いたい方はここを修正してください。

# WebDriverを起動する
def isLaunch(chromedriver_path='chromedriver.exe'):
    service = Service(executable_path=chromedriver_path)
    try:
        driver = webdriver.Chrome(service=service)
        print('起動に成功。問題なし。')
        driver.quit()
        return True
    except (FileNotFoundError, WebDriverException, SessionNotCreatedException) as e:
        print("エラー詳細:", str(e))  # エラーメッセージの詳細を出力
        return e

指定のWebDriverのダウンロード

バージョンの確認は次にします。
ここでは指定したバージョンのダウンロード部分のメソッドです。
zipファイルでダウンロードされるので中身をカレントディレクトリに解凍します。
最後にZipファイルはいらないので削除しました。
Windows以外の方はfile_urlの部分を変えてください。
以下にダウンロードのURLが書かれています。
https://googlechromelabs.github.io/chrome-for-testing/

# 指定されたバージョンのWebDriverをダウンロードする関数
def download_webdriver_version(version):
    file_url = f"https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/{version}/win32/chromedriver-win32.zip"
    save_path = "./download_webdriver.zip"
    print(version + ' のバージョンをダウンロードします。')
    # zipファイルをダウンロード
    with urllib.request.urlopen(file_url) as download_file:
        data = download_file.read()
        with open(save_path, mode='wb') as save_file:
            save_file.write(data)
    # ダウンロードしたzipファイルを解凍
    with zipfile.ZipFile("./download_webdriver.zip") as obj_zip:
        with obj_zip.open('chromedriver-win32/chromedriver.exe') as src, open('./chromedriver.exe', 'wb') as dst:
            dst.write(src.read())
    # zipファイルはいらないので削除 
    os.remove('./download_webdriver.zip')
    print("ダウンロード完了")

最新バージョンを取得

driverがない場合最新バージョンをダウンロードさせたいので取得していきます。
今回は安定版でいいので「stable」のものを選びます。
URLはこちらです。
https://googlechromelabs.github.io/chrome-for-testing/
bs4を使ってバージョンを取得してみました。

# 最新のWebDriverのバージョンを取得する関数
def get_latest_webdriver_version():
    response = requests.get(LATEST_VERSION_URL)
    soup = BeautifulSoup(response.content, 'html.parser')

    response = requests.get(LATEST_VERSION_URL)
    soup = BeautifulSoup(response.content, 'html.parser')

    td_element = soup.find(string="Stable").find_next('td')
    stable_version = td_element.find("code").text
    return stable_version

WebDriverのダウンロードと起動を試みるメソッド

最後のメソッドです。
上記のものを合わせたものですね。
起動に失敗した場合にこのメソッドを呼び出します。
動作としては、エラーメッセージにバージョンが書かれていればそのバージョンをダウンロード
なかった場合はとりあえず最新バージョンをダウンロードします。
そして、起動確認ですね。

# WebDriverのダウンロードと起動を試みる関数
def download_and_launch_webdriver():
    # エラーメッセージから現在のバージョンを取得
    match = re.search(r'(?<=\bchrome=)\d+', str(error))
    if match:
        current_version = match.group()
        print("chromeのversionは " + current_version)
    else:
        print("エラーメッセージからChromeのバージョンを取得できませんでした。最新のバージョンを取得します。")
        current_version = get_latest_webdriver_version()
        if not current_version:
            print("最新のWebDriverのバージョンを取得できませんでした。")
            return

    # バージョン情報の取得とダウンロード
    download_webdriver_version(current_version)
    if isLaunch() is True:
        print("WebDriverの更新と起動に成功しました。")
    else:
        print("更新後のWebDriverの起動に失敗しました。")

メインの実行部分

今までのメソッドを実行する部分です。
ここは完全にChatGPTさんの出力したものです。
isinstanceってものを始めて知りましたがこれは便利だなと感じたのでこれから使っていこうと思います。
以下に参考を貼っておきます。
isinstance関数の使い方(オブジェクトのデータ型を判定する)

# 以下、メインの実行部分
error = isLaunch()
if isinstance(error, (SessionNotCreatedException, FileNotFoundError, WebDriverException)):
    download_and_launch_webdriver()
else:
    print("その他のエラー:" + str(error))

全体

最後に全体のコードです。

import os
import re
import zipfile
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.common.exceptions import SessionNotCreatedException, WebDriverException
import urllib.request
import requests
from bs4 import BeautifulSoup

# WebDriverのダウンロード元のURL
WEBDRIVER_BASE_URL = "https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/"

# 最新バージョンを取得するためのURL
LATEST_VERSION_URL = "https://googlechromelabs.github.io/chrome-for-testing/"

# WebDriverを起動する
def isLaunch(chromedriver_path='chromedriver.exe'):
    service = Service(executable_path=chromedriver_path)
    try:
        driver = webdriver.Chrome(service=service)
        print('起動に成功。問題なし。')
        driver.quit()
        return True
    except (FileNotFoundError, WebDriverException, SessionNotCreatedException) as e:
        print("エラー詳細:", str(e))  # エラーメッセージの詳細を出力
        return e

# 最新のWebDriverのバージョンを取得する関数
def get_latest_webdriver_version():
    response = requests.get(LATEST_VERSION_URL)
    soup = BeautifulSoup(response.content, 'html.parser')

    response = requests.get(LATEST_VERSION_URL)
    soup = BeautifulSoup(response.content, 'html.parser')

    td_element = soup.find(string="Stable").find_next('td')
    stable_version = td_element.find("code").text
    return stable_version

# 指定されたバージョンのWebDriverをダウンロードする関数
def download_webdriver_version(version):
    file_url = f"https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/{version}/win32/chromedriver-win32.zip"
    save_path = "./download_webdriver.zip"
    print(version + ' のバージョンをダウンロードします。')
    # zipファイルをダウンロード
    with urllib.request.urlopen(file_url) as download_file:
        data = download_file.read()
        with open(save_path, mode='wb') as save_file:
            save_file.write(data)
    # ダウンロードしたzipファイルを解凍
    with zipfile.ZipFile("./download_webdriver.zip") as obj_zip:
        with obj_zip.open('chromedriver-win32/chromedriver.exe') as src, open('./chromedriver.exe', 'wb') as dst:
            dst.write(src.read())
    # zipファイルはいらないので削除 
    os.remove('./download_webdriver.zip')
    print("ダウンロード完了")

# WebDriverのダウンロードと起動を試みる関数
def download_and_launch_webdriver():
    # エラーメッセージから現在のバージョンを取得
    match = re.search(r'(?<=\bchrome=)\d+', str(error))
    if match:
        current_version = match.group()
        print("chromeのversionは " + current_version)
    else:
        print("エラーメッセージからChromeのバージョンを取得できませんでした。最新のバージョンを取得します。")
        current_version = get_latest_webdriver_version()
        if not current_version:
            print("最新のWebDriverのバージョンを取得できませんでした。")
            return

    # バージョン情報の取得とダウンロード
    download_webdriver_version(current_version)
    if isLaunch() is True:
        print("WebDriverの更新と起動に成功しました。")
    else:
        print("更新後のWebDriverの起動に失敗しました。")

# 以下、メインの実行部分
error = isLaunch()
if isinstance(error, (SessionNotCreatedException, FileNotFoundError, WebDriverException)):
    download_and_launch_webdriver()
else:
    print("その他のエラー:" + str(error))

Discussion