はじめに
Excelでwebブラウザの操作を自動化する最小機能のみ実装したフレームワークの「TinySeleniumVBA」があります。
これは今のところActiveXを使用しているため、Windows専用になっています。ActiveXの部分を取り除き代替部分をVBA-toolsライブラリー群を使えば、Mac上のExcelで動作するかもと取り組みました。
VBA-toolsを用いてWindows上では動作するようになったのですが、残念ながらMacではエラーで動作しませんでした。
何が原因なのか分からないため、MacにSeleniumをPythonで動かしてみようと思った次第です。
簡単かと思ったら結構ハマったので記事にしてみました。
【2023/06/06追記】
自記事は少し古いので、この記事を参考に新しいバージョン(Selenium 4.9.1)で動くように対応とのこと。
【2023/10/14追記】
Selenium 4.6以降から、ドライバのインストールツールである Selenium Manager が操作対象となるウェブブラウザのバージョンも考慮してドライバをインストールしてくれるようになっています。
環境構築
- Mac Book Pro(2.3 GHz 8コアIntel Core i9) Monterey 12.2.1
- Google Chrome Ver.100.0.4896.60(Official Build)
- Python 2.7.18 と Python 3.9.4 共存した状態
Seleniumのインストール
pip3 install selenium
今回は、selenium ver 4.1.3 が入りました。
pipとpip3の違い
Python 2系とPython 3系が共存する環境では、pip
はPython2、pip3
はPython3にインストールされます。
どちらか一方であれば、pip
を使用すればいいです。
Google Chromeドライバのインストール
右端上部にある「⋮」のメニュー → ヘルプ → Google Chromeについて
(例)
Chrome は最新の状態です
バージョン: 100.0.4896.60(Official Build) (x86_64)
pip3 install chromedriver-binary-auto
バージョンを自動判断してインストールされることを期待するも、エラーでインストールできませんでした。
バージョンを指定する
バージョンを入れないまま実行するとバージョンの一覧が表示されます。
pip3 install chromedriver-binary==
ERROR: Could not find a version that satisfies the requirement chromedriver-binary==
(from versions: 2.29.1, 2.31.1, 2.33.1, 2.34.0, 2.35.0, 2.35.1, 2.36.0, 2.37.0, 2.38.0, 2.39.0,
⋮
99.0.4844.17.0, 99.0.4844.35.0, 99.0.4844.51.0, 100.0.4896.20.0, 100.0.4896.60.0, 101.0.4951.15.0)
ERROR: No matching distribution found for chromedriver-binary==
確認したChromeのバージョンと一致するものを指定します。
ChromeDriverのバージョンはそこまで厳密に合わせる必要はありません。
以下公式の「バージョンの選び方」説明ページで、最後の桁はあっていなくても良いと書かれています。一番番号が近いものを使いましょう。
Each version of ChromeDriver supports Chrome with matching major, minor, and build version numbers. For example, ChromeDriver 73.0.3683.20 supports all Chrome versions that start with 73.0.3683.
↓翻訳
ChromeDriverの各バージョンは、メジャー、マイナー、ビルドの各バージョン番号が一致するChromeに対応しています。例えば、ChromeDriver 73.0.3683.20は73.0.3683で始まるすべてのChromeのバージョンをサポートします。
https://chromedriver.chromium.org/downloads/version-selection
# ChromeDriverのインストール
pip3 install chromedriver-binary==「確認したChromeのバージョン」
# 自分の環境だとこんな感じ
pip3 install chromedriver-binary==100.0.4896.60.0
Collecting chromedriver-binary==100.0.4896.60.0
Using cached chromedriver-binary-100.0.4896.60.0.tar.gz (4.9 kB)
Preparing metadata (setup.py) ... done
Using legacy 'setup.py install' for chromedriver-binary, since package 'wheel' is not installed.
Installing collected packages: chromedriver-binary
Running setup.py install for chromedriver-binary ... done
Successfully installed chromedriver-binary-100.0.4896.60.0
【2023/11/24追記】
久しぶりに、chromedriverをインストール。
現在のバージョンは、119.0.6045.159 ですが、No matching となったので、119.0.6045.105.0を指定してインストールするも、エラーが発生
% pip install chromedriver-binary==119.0.6045.159
ERROR: No matching distribution found for chromedriver-binary==119.0.6045.159
% pip install chromedriver-binary==119.0.6045.105.0
error: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)>
下記サイトを参考にしてみた。
# こっちでは駄目だった。
% pip install --upgrade certifi
# こっちなら成功 ※ Pythonのバージョンを合わせることが必要!
% open /Applications/Python\3.9/Install\Certificates.command
% pip install chromedriver-binary==119.0.6045.105.0
Successfully installed chromedriver-binary-119.0.6045.105.0
インストールの場所は、pip show chromedriver-binary
のLocationで分かる。
更に配下のchromedriver_binary/chromedriver
※ 間の -
は _
になっている。
% pip show chromedriver-binary
Name: chromedriver-binary
Version: 119.0.6045.105.0
Summary: Installer for chromedriver.
Home-page: https://github.com/danielkaiser/python-chromedriver-binary
Author: Daniel Kaiser
Author-email: daniel.kaiser94@gmail.com
License: MIT
Location: /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages
Requires:
Required-by:
ダウンロードサイトから取得してインストール
それでもpip
でインストールできない場合、ChromeDriverのダウンロードサイトから近いバージョンのものをダウンロードします。
その場合、/usr/local/bin/
フォルダにchromedriverを入れました。
実行する
python3 selenium-test.py
実行時に「開発元を検証できないため開けません」が表示されたら、下記サイトを参考にしてください。
ソースコード
Chromeを起動して、Google検索で"Selenium"を検索する。
Selenium 4で「DeprecationWarning」が出る場合の対策
今回はTinySeleniumVBAでも使用できるように、ChromeDriverは/usr/local/bin/
フォルダに配置しました。pip
コマンドでインストールした場合、executable_pathの指定は不要です。
# ブラウザを開く
chrome_service = fs.Service(executable_path='/usr/local/bin/chromedriver')
↓
import chromedriver_binary
# ブラウザを開く
chrome_service = fs.Service()
# coding:utf-8
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from time import sleep
from selenium.webdriver.chrome import service as fs
# ブラウザを開く
chrome_service = fs.Service(executable_path='/usr/local/bin/chromedriver')
driver = webdriver.Chrome(service=chrome_service)
# Googleの検索TOP画面を開く
driver.get("https://www.google.co.jp/")
# 検索語として「selenium」と入力し、Enterキーを押す。
search = driver.find_element_by_name('q')
search.send_keys("selenium")
search.send_keys(Keys.ENTER)
# 5秒間待機してみる。
sleep(5)
# ブラウザを終了する。
driver.close()
結果
プロセスが残る
driver.close()では、プロセスが残ったままになります。何度も実行すると大量に残ったまま。
ps aux | grep chromedriver
yaju 88651 0.0 0.1 67767416 10180 s000 S 11:24PM 0:00.12 /usr/local/bin/chromedriver --port=56927
yaju 88589 0.0 0.1 67776632 10492 s000 S 11:24PM 0:00.12 /usr/local/bin/chromedriver --port=56893
yaju 88533 0.0 0.1 67767416 10640 s000 S 11:24PM 0:00.12 /usr/local/bin/chromedriver --port=56863
yaju 87247 0.0 0.1 67767416 9316 s000 S 11:14PM 0:00.14 /usr/local/bin/chromedriver --port=56769
yaju 47776 0.0 0.0 67390920 3620 ?? S 5:21PM 0:00.37 /usr/local/bin/chromedriver
yaju 89272 0.0 0.0 34132100 916 s000 S+ 11:29PM 0:00.00 grep chromedriver
killall chromedriver でプロセスを全て終了します。
killall chromedriver
ps aux | grep chromedriver
yaju 90473 0.0 0.0 34122884 880 s000 S+ 11:38PM 0:00.00 grep chromedriver
quit()を使用する
close()は現在のウィンドウの終了で、quit()は全てのウインドウとドライバーの終了という違いがあるが、ChromeDriverではquit()の実装がService.stop()も呼ぶようになっている。
with構文を使う
Webdriverの実装を見てみると、__exit__でquit()が呼ばれているのでwith構文を使えば同じことができる。
class WebDriver(BaseWebDriver):
def __exit__(self, *args):
self.quit()
with構文で書き換えてみる。
# coding:utf-8
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from time import sleep
from selenium.webdriver.chrome import service as fs
#import chromedriver_binary
# ブラウザを開く。
chrome_service = fs.Service(executable_path='/usr/local/bin/chromedriver')
with webdriver.Chrome(service=chrome_service) as driver:
# Googleの検索TOP画面を開く。
driver.get("https://www.google.co.jp/")
# 検索語として「selenium」と入力し、Enterキーを押す。
search = driver.find_element_by_name('q')
search.send_keys("selenium")
search.send_keys(Keys.ENTER)
# 5秒間待機してみる。
sleep(5)
ブラウザを開いたまま処理を終了する
close()やquit()は使わず、chromeを開いたままプロセスを終了させます。
from selenium import webdriver
import os
import signal
driver = webdriver.Chrome(service=chrome_service)
try:
# ~いろいろな処理~
finally:
os.kill(driver.service.process.pid,signal.SIGTERM)
最後に
SeleniumをPythonで動かすことができました。
MacでTinySeleniumVBAが動作しないのは、下記サイトで仕組みを知ることで原因が分かりました。
MacではExcelのバージョンによってShellコマンドを使用して、chromedriverを起動することが出来なくなっていたためでした。調査した結果、AppleScriptTask コマンドを使用しAppleScript スクリプト側でchromedriverが起動させることで解決できました。