ChromeDriverを自動更新するのはなぜ?
- 自分のPCで画面操作の自動化をするにあたり、UiPathやPower Automateがある
- シンプルに実装する場合や画面のテスト実行時にSeleniumが使用されており、画面操作の自動化をプログラムとして実装する場合に利用することが多い
- 以前からSeleniumのChromeDriverを利用していたが、通常操作のChromeのバージョンに合わせて手作業でChromeDriverの更新が面倒
- システマティックに操作したいため、自動化を検討した
結果
- 自動化は可能そう
- 本日から稼働するため、挙動は今後検討しなければいけない可能性はある
-
ソースコード群はGithub上で展開していますので、良ければStarください
- root/data/フォルダ配下に実際のデータが格納されるので、適宜調整してください
- 開発時間は2時間程度
必要な技術
- requests
- zipfile
- json
実装環境
- Windows 10
- Python 3.6.8(前から使っている古いバージョン)
実装内容について
参考ページ
- 不採用
- 理由: 参考にはなったが、Chromeの自動化を実装するにあたり、なるべく原始的な処理で進めたかったため.
-
採用
- 理由: 直接Chromeからバージョンを取得できるため、コマンドプロンプトを使用するが必要経費として利用した
現在使用しているChromeのバージョンの取得
- Chromeのバージョンを直接取得するために、バッチで出力させた結果をテキストに出力することで後続処理に対応
get_chrome_version.bat
dir /B /O-N "C:\Program Files\Google\Chrome\Application" | findstr ^[0-9].* > ".\..\data\chrome_version.txt"
公開しているChromeのバージョン(Json)を取得&保存
- ChromeのバージョンはJsonで提供されている
- 最新のデータを取得しJsonの結果を保存することで、後続で利用可能にする
get-json.py
# 対象のURLからjsonデータを取得
json_name = "known-good-versions-with-downloads.json"
json_url = f"https://googlechromelabs.github.io/chrome-for-testing/{json_name}"
# json_url = "http://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json"
print(json_url)
# 上記のURLからrequestsでjsonデータを取得
import requests
# プロトコルはhttpsで、jsonデータを取得
response = requests.get(json_url)
print(response)
# jsonデータを取得
json_data = response.json()
# print(json_data)
import datetime
now_datetime = datetime.datetime.now()
print(now_datetime)
now_datetime_str = now_datetime.strftime("%Y%m%d-%H%M%S")
import os
save_dir_json_file_path = "./data/json"
os.makedirs(save_dir_json_file_path, exist_ok=True)
# jsonファイルを保存
save_json_file_path = f"{save_dir_json_file_path}/{now_datetime_str}-{json_name}"
import json
with open(save_json_file_path, "w") as f:
json.dump(json_data, f, indent=4)
Chromeのバージョンと、Chromeのバージョン管理Jsonの突合
- 現在利用しているChromeのバージョンとダウンロードしたJsonとを突合する
- 最新のChromeではなく、その1つ前のバージョンを取得する
- 取得したChromeのURLをChromeDriverに変換しダウンロード&展開する
read-json.py
# Chrome Versionを取得しておく
# ChromeDriverのバージョンを取得する
with open("./data/chrome_version.txt", "r") as f:
chrome_version = f.read()
print(chrome_version)
# chrome_version は最終行ので取得する
now_chrome_version = chrome_version.split("\n")[-2]
print(now_chrome_version)
split_now_chrome_version = [int(x) for x in now_chrome_version.split(".")]
## 保存したファイルを読み込み利用可能な状態にする
json_name = "known-good-versions-with-downloads.json"
# print(json_name)
json_dir_file_path = "./data/json"
# jsonファイル一覧を取得し、最新のjsonファイルを取得する
import glob
import os
json_files = glob.glob(f"{json_dir_file_path}/*.json")
latest_json_file_path = max(json_files, key=os.path.getctime)
print(latest_json_file_path)
# このデータを利用する
import json
with open(latest_json_file_path, "r") as f:
json_data = json.load(f)
# print(json_data)
# print(type(json_data))
for first_key, value in json_data.items():
# print(first_key, value)
print(first_key)
key_timestamp = "timestamp"
# print(json_data[key_timestamp])
key_versions = "versions"
key_version = "version"
# print(json_data[key_versions])
# print(type(json_data[key_versions]))
json_data_versions = json_data[key_versions]
chrome_driver_version_dict = {}
for json_data_idx in range(0, len(json_data_versions)):
json_data_version = json_data_versions[json_data_idx]
chrome_driver_version_dict[json_data_idx] = {}
# print(json_data_version)
# print(type(json_data_version))
"""json_data_version layout
version 113.0.5672.0
revision 1121455
downloads {'chrome': [{'platform': 'linux64', 'url': 'https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/113.0.5672.0/linux64/chrome-linux64.zip'}, {'platform': 'mac-arm64', 'url': 'https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/113.0.5672.0/mac-arm64/chrome-mac-arm64.zip'}, {'platform': 'mac-x64', 'url': 'https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/113.0.5672.0/mac-x64/chrome-mac-x64.zip'}, {'platform': 'win32', 'url': 'https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/113.0.5672.0/win32/chrome-win32.zip'}, {'platform': 'win64', 'url': 'https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/113.0.5672.0/win64/chrome-win64.zip'}]}
"""
# for key_seconds, value in json_data_version.items():
# print(key_seconds, value)
# key_version = "version"
key_revision = "revision"
key_downloads = "downloads"
json_data_version_version = json_data_version[key_version]
# print(json_data_version_version)
json_data_version_revision = json_data_version[key_revision]
# print(json_data_version_revision)
json_data_version_downloads = json_data_version[key_downloads]
# print(json_data_version_downloads)
json_data_version_downloads_chrome = json_data_version_downloads["chrome"]
# print(type(json_data_version_downloads_chrome))
# print(json_data_version_downloads_chrome)
target_os_type = "win64"
key_platform = "platform"
for dl_chrome_idx in range(0, len(json_data_version_downloads_chrome)):
json_data_version_downloads_chrome_dict = json_data_version_downloads_chrome[
dl_chrome_idx
]
# print(json_data_version_downloads_chrome_dict)
if json_data_version_downloads_chrome_dict[key_platform] == target_os_type:
# print(json_data_version_downloads_chrome_dict)
break
# break
chrome_driver_version_dict[json_data_idx][key_version] = json_data_version_version
chrome_driver_version_dict[json_data_idx][key_revision] = json_data_version_revision
# chrome_driver_version_dict[json_data_idx][key_downloads] = json_data_version_downloads
chrome_driver_version_dict[json_data_idx][
key_platform
] = json_data_version_downloads_chrome_dict["url"]
# print(chrome_driver_version_dict)
for json_data_idx in chrome_driver_version_dict.keys():
# print(json_data_idx, chrome_driver_version_dict[json_data_idx])
version = chrome_driver_version_dict[json_data_idx][key_version]
split_version = [int(x) for x in version.split(".")]
# print(split_version, split_now_chrome_version)
if split_version[0] == split_now_chrome_version[0]:
# print(split_version, split_now_chrome_version)
if split_version[1] == split_now_chrome_version[1]:
# print(split_version, split_now_chrome_version)
if split_version[2] == split_now_chrome_version[2]:
print(split_version, split_now_chrome_version)
if split_version[3] >= split_now_chrome_version[3]:
print(split_version[3], split_now_chrome_version[3])
print("OK")
break
if split_version[0] > split_now_chrome_version[0]:
break
# if version == now_chrome_version:
# print("OK")
# break
# print(chrome_driver_version_dict[json_data_idx][key_version])
print(chrome_driver_version_dict[json_data_idx - 1][key_version])
print(chrome_driver_version_dict[json_data_idx - 1])
# 上記のデータをダウンロードする
chrome_download_url = chrome_driver_version_dict[json_data_idx - 1][key_platform]
split_chrome_download_url = chrome_download_url.split("/")
chrome_driver_download_url = (
"/".join(split_chrome_download_url[:-1])
+ "/"
+ split_chrome_download_url[-1].replace("chrome", "chromedriver")
)
# https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/120.0.6099.109/win64/chrome-win64.zip
# https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/120.0.6099.109/win64/chromedriver-win64.zip
print(chrome_driver_download_url)
import io
import zipfile
import requests
extract_dir = ".\data"
response = requests.get(chrome_driver_download_url)
bytes_io = io.BytesIO(response.content)
with zipfile.ZipFile(bytes_io) as zip:
zip.extractall(extract_dir)
終わりに
- シンプルな実装(リリースなどはしない)ものであれば、Copilotと一緒に開発すればハードルはだいぶ下がったのが良かった
- もちろん、Copilotの実装で動かない場合もあるから注意は必要
- イメージがあれば、結構な開発速度になっていそう
- ChromeDriverのアップデートについては記事が少なかったのが意外だった
- また何かあれば記事を書いていく予定
- 興味がある人がいればいいねや「XXXの実装をしてほしい」などをコメントに記載いただければ検討します