RPA で大変な割に需要が多いことNo.1といえばブラウザの操作ではないでしょうか? 日本のクラウド化が遅れているとはいえ、クラウドやSaaSを一切導入していない会社というのは珍しいと思います。仮に会社で導入していなくても、個人では使っている人がほとんどだと思います。
そんなブラウザ・Webサイトの操作は大変です。同じ環境で動作させても、配置・時間が不安定だったりします。また、ローカルのソフトウェアよりもアップデートによってUIが変わりやすいことも特徴です。
一方で、ブラウザを自在に操作できれば情報収集やネットワーク関連の機能にもアクセスしやすくなります。Python で行えば、デスクトップの RPA はもちろん、その他の「プログラム的な機能」と組み合わせることができるので、他の GUI 系の RPA ソリューションに対して優位性になります。
Selenium はこの他に元々の使い方である Webサービスのデバッグ / テストツール としての活用や RPA と少し似た、情報収集を自動化・効率化するスクレイピングにも活用されます。RPAに限らず有効に活用できるライブラリなので、頑張って学習しましょう。
- Python に Selenium をインストールする
- WebDriver をインストールして Chrome を操作できるようにする
- Google を開いて検索する
- XPath と CSS セレクタについて
Python に Selenium をインストールする
Python でWeb サイトにアクセスする場合には、 urllibや、requests といった方法があります。これはこれで使い道があるのですが、私たちが学んでいるのは RPA です(いまのところ)。人間と同じようにブラウザを操作することにしましょう。その方が、コンピューターの内部 や Web 技術に詳しくなくても自動化しやすいです。
py -m pip install selenium
と、PowerShellで入力して Selenium と依存関係にあるパッケージをインストールします(Mac や Linux の方は py -mの部分なしで、pipから直接起動してください)。
ずらずらっと色々出て来て、最後に
Successfully installed async-generator-1.10 attrs-21.4.0 certifi-2021.10.8 cffi-1.15.0 cryptography-36.0.1 h11-0.13.0 idna-3.3 outcome-1.1.0 pyOpenSSL-21.0.0 pycparser-2.21 selenium-4.1.0 sniffio-1.2.0 sor
tedcontainers-2.4.0 trio-0.19.0 trio-websocket-0.9.2 urllib3-1.26.8 wsproto-1.0.0
のように「Seccessfully installed」の文字が出てくれば成功です。ネットワーク系・暗号化系のライブラリが多く追加でインストールされます。インストールされたものを全て覚えている必要はないですが、ざっと名前を眺めておくと後々役に立つこともあるので見ておくといいでしょう。
WebDriverをインストールする
実はこれだけではブラウザを操作できません。今インストールした Selenium は、ブラウザを操作する WebDriver という中間ソフトに接続して、WebDriver に命令・お願いするためのパッケージです。実際にブラウザを操作するのは、 WebDriver という中間ソフト(ドライバ)となります。
とりあえず、今回は、Chromeを利用することにします。
Chromeのバージョンを確認
WebDriver は OSごと、ブラウザごと、バージョンごとに分かれているのでまずはバージョンを確認します。
上記URL をコピーし、ChromeのURL入力欄に貼り付けて設定ページを開きます(リンクからは開けません)。
設定ページが開いたら、
- 左メニューから「Chromeについて」を選択
- バージョンの数字を確認
バージョンは非常に長いですが、.(ドット)で区切られた先頭の桁を覚えておけば大丈夫です。画像では、97ですね。
確認できたら、次のステップに進みます。
WebDriverのダウンロードとインストール
上記のダウンロードページにアクセスします。すると、先頭に「Current Releases」の文字があり、その下にIf you are using…とリストが続きます。
ここで、先ほど覚えておいたChromeのバージョンと比較して、先頭の桁(.区切り)の数字と同じ Chrome version のChromeDriverのリンクをクリックします。
注意点は、Chromeが最新バージョンであってもここで一番新しいものとは限らない(βバージョン等もある)ことと、ChromeDriver のバージョンの数字と、Chrome のバージョンの数字は、先頭以外一致していなくても問題ないことです。あくまでも、ドットで区切られた最初の数字を目安にリンクをクリックしてください。
リンクをクリックすると、各OS用のダウンロードがあります。使っている OS にあわせてダウンロードしてください。数字がついていますが、基本的に32bit, 64bitは気にしなくて大丈夫です。ただし、Mac ユーザーは最近出たM1チップを使っている場合は、m1とついている方をダウンロードするようにしましょう(CPUが異なるため)。
ダウンロードできたら、自由な場所に中のchromedriver.exe (windowsの場合)を展開しましょう。
場所は自由ですが、できるだけパスにスペースや日本語が入らず、かつ短い場所がおすすめです。
楽介の場合は、「D:\bin\WebDriver\ChromeDriver\97」とバージョンまで含めて格納しましたが、使うブラウザは常に一つだよという場合には、この例で言えばD:\binの中に直接入れるくらいでも問題ないと思います。ただし、インストールした場所はどこかに控えておいて忘れないようにしましょう。
ここまでで、Pythonからブラウザ を操作する準備は完了です。
なんで Selenium と WebDriverを別々にインストールするの?
この項目は、ソフトウェアの動作・設計についてより理解を深めたい人向けです。興味がある方だけ読んでください。
なんでこのような仕組みになっているかですが、ダウンロード時に見たようにWebDriverはブラウザごと、バージョンごとに使えるものが細かく分かれています。もちろん、OSごとにも違いますし、Mac では CPU が Intel 製か Apple 純正の M1 かによっても異なりました。
それを Python のパッケージ管理でやると余りにも大変なので、 WebDriver という共通のインターフェイスをもつ中間ソフトが間に入って、いい感じにブラウザごとの違いを吸収してくれているというわけです。
現代の OS は非常に高度で意識することが少ないですが、そもそも OS がハードウェアの違いを吸収して、私たちに基本的な操作を提供してくれています。メーカーが違っても、同じように操作できるのは、同じ OS を導入しているからですね(Mac は Apple 製のみですが)。
その OS にしても、各メーカーのハードウェアの違いを全て把握することはできません。そこで、ハードウェアメーカーは、ドライバーやBIOSといった基本的なソフトウェアを提供することで、ハードウェアを OS が利用できるようにしてくれています。
極端な話ですが、 Python もコンピューターが理解するマシン語に変換するための中間ソフトウェアです。OS ごとに Python の実行ファイル(インタープリタ)があることによって OS 依存の機能を使わない限り、Windows で書いた Python がMac でも Linux でも動作してくれます。
Selenium を使って見る
では、Chapter-11-1.pyとして Python ファイルを作成します。
from selenium import webdriver
from selenium.webdriver.chrome import service as chrome_service
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
import time
cs = chrome_service.Service(executable_path = r'D:\bin\WebDriver\ChromeDriver\97\chromedriver.exe')
webd = webdriver.Chrome(service = cs)
webd.get('https://www.google.com/')
各自の環境にあわせて executable_path 引数を書き換えるのを忘れないようにしてください。
この Python を起動すると、Chrome ブラウザが起動します。webd.get 関数に Google の URL を渡したのでgoogle のページが表示されている点を確認してください。
これが Selenium で Chrome ブラウザを操作する一番基本的な書き方です。最初に開く Web サイトを別のものにしたければ、get 関数に渡す引数のURLを変更します。
起動したブラウザには「Chrome は自動テストソフトウェアによって制御されています。」と注釈が表示され、Selenium と WebDriver で起動したものであることが分かります。Chrome のユーザーも含めて、様々なログイン状態も普段のブラウザとは別扱いとなります。この点、便利な点もありますが不便な部分もありますので注意してください。
検索してみる
Google といったら検索エンジンですから、検索してみましょう。
検索するには、検索したい文字列をテキストボックスに入力しなくてはいけません。もちろん PyAutoGUIなどを使うこともできますが、まずは XPath という強力な仕組みを使います。
XPath というのは、HTML や XML を Python のようなプログラムで効率的に解析・探索するための専用の記法です。
Python だけでも大変なのに、新しい記法なんて覚えられないという方も大丈夫です。比較的分かりやすい上に、 RPA で使用するくらいであれば補助ツールが使えます。一番手軽な補助ツールは、 Chrome に最初から内蔵されています。
まずは、Chrome から、Google の検索フォームを右クリックします。出て来たコンテキストメニューから、「検証」をクリックします。
すると、Chrome の Developer Tool というツールが起動してブラウザに表示されます。
<input class=”gLFyf… のような部分が反転して色づいているはずなので(上図参照)、そこを右クリックします。もし、inputが反転していなかったら、改めて右クリックから検証を探して下さい(Developer Toolが使える方は、もちろん手動で探しても大丈夫です)。
現れたコンテキストメニューから、「コピー→XPath をコピー」または、「コピー→完全な XPath をコピー」とたどります。これで Selenium で使いたいXPath がコピーできました。
RPA ではこのように、操作したいただひとつの要素がはっきりしている場合が多いので、 XPath などの理解はそこまで深くしなくても大丈夫なことが多いです。
XPath が準備できたところで、Python ファイルを以下のように書き換えます。
from selenium import webdriver
from selenium.webdriver.chrome import service as chrome_service
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
import time
cs = chrome_service.Service(executable_path = r'D:\bin\WebDriver\ChromeDriver\97\chromedriver.exe')
webd = webdriver.Chrome(service = cs)
webd.get('https://www.google.com/')
time.sleep(3)
xpath = '/html/body/div[1]/div[3]/form/div[1]/div[1]/div[1]/div/div[2]/input' #ここにコピーしたxpathを入力する
form = webd.find_element(By.XPATH, xpath)
form.send_keys('python' + Keys.RETURN)
実行して、Python という文字が検索されたことを確認してください。
追加された部分の解説
find_element 関数は、第1引数に指定された方法で Web ページを構成する要素(HTML要素)を検索して特定する関数です。ここでは、By.XPATH を指定しているので、XPath を使って HTML を検索します。第2引数には、もちろん、XPath を格納したxpath 変数が指定されています。
find_element 関数の返り値には、見つかった要素のオブジェクトが入っていますので、これを用いて実際のブラウザの操作を行います。
ここでは、send_keys関数で、キー操作を送信します。PyAutoGUI で言う、write 関数のようなものです。「python」と入力した後に、Enterキーで確定したいので、Keys.RETURN を加えて実行しています。
操作したい部分を指定して、それから操作を入力するという基本的な流れは、RPA と変わらないですね。操作部分の特定方法が大きく異なる点と、使う関数が PyAutoGUI のものではないことが違いですが、大体、ライブラリが違っても似た使い方になっているので戸惑いは少ないと思います。
write関数では、日本語が入力できませんでした。それはキーボードの入力を再現する関数だったからです。
ではsend_keys関数ではどうでしょうか? 引数を色々変えて試して見ましょう。
CSS セレクタを使って見る
Selenium で要素を特定する方法はこれだけではありません。他にも沢山ありますが、同じく強力で汎用的な、 CSSセレクタのやり方も試して見ます。
CSS セレクタもChromeからコピーができます。同じく、inputを右クリックして、「コピー→selector をコピー」とすることで、XPath の代わりに CSS セレクタをコピーできます。
コピーできたら、以下のようにPython を書き換えます。
from selenium import webdriver
from selenium.webdriver.chrome import service as chrome_service
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
import time
cs = chrome_service.Service(executable_path = r'D:\bin\WebDriver\ChromeDriver\97\chromedriver.exe')
webd = webdriver.Chrome(service = cs)
webd.get('https://www.google.com/')
time.sleep(3)
#xpath = '/html/body/div[1]/div[3]/form/div[1]/div[1]/div[1]/div/div[2]/input' #ここにコピーしたxpathを入力する
csss = 'body > div.L3eUgb > div.o3j99.ikrT4e.om7nvf > form > div:nth-child(1) > div.A8SBwf > div.RNNXgb > div > div.a4bIc > input' #ここにコピーしたselectorを入力する
#form = webd.find_element(By.XPATH, xpath)
form = webd.find_element(By.CSS_SELECTOR, csss)
form.send_keys('python' + Keys.RETURN)
Python スクリプトは上記のように変更します。xpath 変数の代わりに csss 変数を作り、find_element 関数の第1引数が、By.XPATH から、By.CSS_SELECTOR に変わっています。これにより、Web ページの要素(HTML要素)を見つける手段が、XPath から CSS セレクタに変わります。
第2引数はもちろん、CSS セレクタの入った csss 変数です。他の部分は変わらず、見つける方法だけ変わっている点を意識してください。見つけるものも変わっていないので、結果も変わりませんね。
XPath と CSS セレクタ、どっちを使えばいいの?
もし、使い慣れているものがあればそちらを使うのがいいです。
XPath は、プログラミングを行うエンジニア向けに作られているので、手動での入力でも配列のように[数字]とすることで、HTMLの何番目というような表現を気軽にできるようにしています。形式的には、XML(HTML) をデータ格納用フォーマットとして捉えていると言えるでしょう。
一方で、 CSS セレクタは HTML を装飾する CSS で、対象とする HTML 要素を特定するために使われる記法です。そのため、親子関係・子孫関係の他 class や id といった方式で指定するときに楽です。
どちらでも、 Chrome などからコピーする場合には手間は同じです。ただ、class や ID がしっかり振られている、いわゆる一般的な Web サイトの場合、class 名や id に加えて子孫関係を表現するだけで要素を特定しやすいです。
筆者の経験上、Chrome からコピーしたような、ルート( html や body )から厳密に親子関係を表現したものでは、少し HTML 構造が変化しただけで動作しなくなるのに対し、途中の構造を省略して特徴的な class 名や id をキーにしたものの方は多少の変更なら手を加えなくても動作する場合があります。
そのため、 class 名や id が多く登場する Web サイトでは CSS セレクタの方が使い勝手がいい場合が多いでしょう。
あくまでも、タイピングにおける労力や、文字数が増えすぎないことでの可読性の面から、 CSS セレクタの方が一般的な Web サイト向けには便利だと考えています。
一方で、もともと XPath が得意だったり、他の RPA ソリューションも使っていて、そちらでは XPath しか使えない場合は XPath を使用するといいでしょう。
どちらかでしか絶対に表現できない方法、というのもあるようですが、実用上はどちらか一方、使い慣れたものがあればそれで十分です。
おわりに
今回は、 Selenium を使って Python からブラウザを操作する基本を学びました。Selenium からブラウザを操作する過程では、 CSS セレクタや XPath といった Web 系の知識・技術を習得することがどうしても必要になってきます。これは最初、覚えることが多くて大変だと思います。
しかし、 Web 系の技術を学習する足がかりとなる知識を RPA を作成する過程で獲得できると考えることもできます。現在の仕事で RPA が必要で学習しており、 Web 系の仕事に興味があるという人は、無駄になりませんね。そもそも、 Selenium はもともとWeb アプリケーションなどのテストツールです。それを RPA に転用しているだけなので、「Selenium でいろんな Web アプリのテストができます!」ということもできますね。
そういった発展性を含めて、 Selenium の学習も頑張っていきましょう。
- Selenium を扱うには、ライブラリの他に WebDriver もインストールする
- WebDriver のお陰で、色々なブラウザの違いを意識せずに操作できる
- XPath や CSS セレクタは Chrome の DeveloperTool (検証)を使うと楽
- キーボード操作などは、PyAutoGUI のものと似ている