LoginSignup
5
8

[Python][Selenium] webdriverの自動更新(webdriver_managerなし)

Last updated at Posted at 2023-01-10

作ったプログラムの備忘録

はじめに

  • 社内LAN環境においてwebdriver_managerが上手く動かないので、webdriver_managerを使わないでも、webdriverの読込みエラーが出た際にレジストリからバージョン確認して、自動更新するようにした
  • 需要はあまりないとは思うがメモとして記載
  • 毎日実行しているが、気づいたら更新されているので、個人的には非常に便利に使っている
  • またexe化して配布する際の初回起動時にwebdriverを同梱しなくても勝手にダウンロードしてくれるのでとても便利

動作テスト環境

OS: Windows 10 Pro 64bit
言語: Python 3.9.13
ライブラリ:Selenium 4.7.2

ソースコード

[2023.04.11追記]importの例外読み込みと例外処理にWebDriverExceptionを追加しました。

全体コード(Edgeの場合)
import os
import winreg
import shutil
import urllib.request
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.edge.service import Service
from selenium.common.exceptions import SessionNotCreatedException
from selenium.common.exceptions import WebDriverException

driver_path = 'edgedriver_win64/msedgedriver.exe'
edge_service = Service(executable_path=driver_path)

try:
    if not os.path.isfile(f'{os.getcwd()}/{driver_path}'):
        raise FileNotFoundError()
    driver = webdriver.Edge(service=edge_service)
except (FileNotFoundError, SessionNotCreatedException, WebDriverException):
    key = winreg.OpenKeyEx(winreg.HKEY_CURRENT_USER, r'SOFTWARE\Microsoft\Edge\BLBeacon')
    ver = winreg.QueryValueEx(key, 'version')[0]
    site = r'https://msedgedriver.azureedge.net/'
    folder_name = 'edgedriver_win64'
    if os.path.exists(folder_name): shutil.rmtree(folder_name)
    webdriver_dl = urllib.request.urlopen(f'{site}{ver}/{folder_name}.zip').read()
    with open(f'{folder_name}.zip', mode="wb") as f:
        f.write(webdriver_dl)
    shutil.unpack_archive(f'{folder_name}.zip', folder_name)
    os.remove(f'{folder_name}.zip')
    driver = webdriver.Edge(service=edge_service)

解説

1. Webdriverのエラー検出

try:
    if not os.path.isfile(f'{os.getcwd()}/{driver_path}'):
        raise FileNotFoundError()
    driver = webdriver.Edge(service=edge_service)
  • そもそもwebdriverが存在しない場合を想定して、FileNotFoundErrorを定義
  • ここのdriver = webdriver.Edge(service=edge_service)でwebdriverのバージョンに起因するエラーが発生するとSessionNotCreatedException(またはWebDriverException)の例外が発生するので、以下のexcept部でwebdriverを自動更新する

2. 例外の定義

except (FileNotFoundError, SessionNotCreatedException, WebDriverException):
  • webdriverが存在しない場合とバージョンが合わない場合に発生する3つの例外を想定
    WebDriverExceptionは記事投稿後に発生したのですが、SessionNotCreatedExceptionとの発生条件の違いがいまいちわかっていません。ただどちらの例外もWebDriverを削除して新しいものに入れ替えないと動かなかったので、例外に追加しています。

3. ブラウザバージョンの確認

Edgeのバージョン確認方法
    key = winreg.OpenKeyEx(winreg.HKEY_CURRENT_USER, r'SOFTWARE\Microsoft\Edge\BLBeacon')
    ver = winreg.QueryValueEx(key, 'version')[0]
chromeのバージョン確認方法
    key = winreg.OpenKeyEx(winreg.HKEY_CURRENT_USER, r"Software\Google\Chrome\BLBeacon")
    ver = winreg.QueryValueEx(key, 'version')[0]
  • レジストリからブラウザのバージョンを取得するコード
  • winregでレジストリの
    HKEY_CURRENT_USER\SOFTWARE\Microsoft\Edge\BLBeacon HKEY_CURRENT_USER\Software\Google\Chrome\BLBeacon
    にあるversion部分を読みに行っている
  • レジストリはオブジェクトとしてtupleでまとめられているので、QueryValueEX以外にもver = winreg.EnumValue(key, 0)[1]などでも取得可能
  • winregの詳細:https://docs.python.org/ja/3.7/library/winreg.html

4. webdriverのダウンロード元情報の定義

edgeの場合のURLとファイル名
    site = r'https://msedgedriver.azureedge.net/'
    folder_name = 'edgedriver_win64'
chromeの場合のURLとファイル名
    site = r'https://chromedriver.storage.googleapis.com/'
    folder_name = 'chromedriver_win32'
  • webdriverのダウンロード元のURLとファイル名を定義

5. 既存のwebdriverの削除

    if os.path.exists(folder_name): shutil.rmtree(folder_name)
  • 既存のwebdriverが存在したら削除

6. webdriverをダウンロード・保存・解凍・zip削除

    webdriver_dl = urllib.request.urlopen(f'{site}{ver}/{folder_name}.zip').read()
    with open(f'{folder_name}.zip', mode="wb") as f:
        f.write(webdriver_dl)
    shutil.unpack_archive(f'{folder_name}.zip', folder_name)
    os.remove(f'{folder_name}.zip')
  • webdriverをダウンロードして保存、解凍、zipの削除を実行

7. 新しいwebdriverの読み込み

    driver = webdriver.Edge(service=edge_service)
  • 最後に自動更新したwebdriverを読み出す

関数化・外部モジュール化

最近は関数化したり、外部モジュール化しておいて、driverを読み込むようにしています。

def load_webdriver():
    driver_path = 'edgedriver_win64/msedgedriver.exe'
    service = Service(executable_path=driver_path)

    # optionsはなくてもOK
    options = EdgeOptions()
    options.add_experimental_option('excludeSwitches', ['enable-logging'])
    options.add_argument('--window-size=1000,1000')

    try:
        if not os.path.isfile(f'{os.getcwd()}/{driver_path}'):
            raise FileNotFoundError()
        driver = webdriver.Edge(service=service, options=options)
    except (FileNotFoundError, SessionNotCreatedException, WebDriverException):
        key = winreg.OpenKeyEx(winreg.HKEY_CURRENT_USER, r'SOFTWARE\Microsoft\Edge\BLBeacon')
        ver = winreg.EnumValue(key, 0)[1]
        site = r'https://msedgedriver.azureedge.net/'
        folder_name = 'edgedriver_win64'
        if os.path.exists(folder_name):
            shutil.rmtree(folder_name)
        webdriver_dl = urllib.request.urlopen(f'{site}{ver}/{folder_name}.zip').read()
        with open(f'{folder_name}.zip', mode="wb") as f:
            f.write(webdriver_dl)
        shutil.unpack_archive(f'{folder_name}.zip', folder_name)
        os.remove(f'{folder_name}.zip')
        driver = webdriver.Edge(service=service, options=options)

    return driver

def main():
    driver = load_webdriver()

5
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
8