Python + Seleniumでブラウザ操作の自動化をしてみた

Python + Seleniumでブラウザ操作の自動化をしてみた

Webブラウザで同じような作業を繰り返す必要がある時に、手動で操作するのが面倒、と感じることがあると思います。
例えばニュースサイトを1日1回見て記事タイトルを10件保存したいという場合に、毎回手動で1つずつタイトルをコピペして、という作業をするのはとても面倒です。他にも、同じような内容をフォームに繰り返し入力するなど、手作業だと時間がかかる場面は多いでしょう。このような場合に役立つのがブラウザ自動化です。

どうやったら自動操作できるのでしょうか。
ブラウザ自動化には様々な方法がありますが、その1つにSeleniumというツールを使う方法があります。Pythonで簡単なコードを書くことでブラウザを思いのままに操作できます。他にもRuby、JavaScriptなど多くの言語に対応しているという特徴があります。
今回はPython、Google Chromeを使って実際に試してみたのでやり方を紹介します。

Seleniumのインストール
Macの方はこちらを見て下さい。
https://scraping-for-beginner.readthedocs.io/ja/latest/src/0.html

Windowsの方はこちらのサイトの「Python環境(Windows)」を見て下さい。
https://www.seleniumqref.com/introduction/webdriver_intro.html

Windowsの方は、ブラウザに対応するドライバを入手する際にこちらからダウンロードします。ダウンロードしたら、自分のPCのどこか分かりやすい場所に展開します。
https://sites.google.com/a/chromium.org/chromedriver/downloads

Chromeのバージョンとドライバのバージョンが違うとエラーとなる場合があります。その際はChromeのバージョンと同じバージョンのドライバをダウンロードして使う必要があるようです。


これで準備完了です。
コードを書いて動作確認してみましょう。
3行目のexecutable_path="..."の箇所には、先程保存したドライバの場所を指定します。
Windowsの場合もMacと同様に、ディレクトリの区切りを / にするとうまく動作します。
ファイル selenium_test.py

from selenium import webdriver
from time import sleep
driver = webdriver.Chrome(executable_path="C:/Users/Aiueo/chromedriver.exe")

driver.get("https://www.google.co.jp")
sleep(3)
elem = driver.find_element_by_class_name("gLFyf")
elem.send_keys("PHP エンジニア")
sleep(3)
elem = driver.find_element_by_class_name("gNO89b")
elem.click()
sleep(5)

driver.quit()


コードを書いたら、次のように実行します。
$ python selenium_test.py
もしくは
$ python3 selenium_test.py

Chromeが起動し、「PHP エンジニア」の検索結果が表示されました。

(PHP_input.png)
(PHP_result.png)

Windowsで画像のようなファイアウォールの警告が出てきた場合は、「アクセスを許可する」をクリックします。

(python_firewall.png)

また、次のようなエラーが出ているかもしれませんが、一応動作はするので気にしなくてよいです。

(usb_device_error.png)


driver.get("URL")と書くと、指定したページにアクセスできます。
動作が速くならないように所々にsleepを入れて、目で見て動作がわかるようにしています。
find_element_by_class_name("クラス名")で、クラス名をもとに要素を取得することができます。Google検索のページではgLFyf、gNO89bなどのクラス名が出てきますが、別のWebサイトでは違うクラス名になりますので、コードを書く時はクラス名を確かめる必要があります。クラス名を知りたい部分（検索boxなど）の上で右クリックし、「検証」をクリックすると確認できます。

ちなみに、Windowsの場合にディレクトリの区切りを \ にするとエラーが出て動かない場合があるので、気をつけましょう。

(path_backslash_error.png)


では次に、「PHP エンジニア」の検索を行った後で「Ruby エンジニア」で検索し、その検索結果のタイトルを5件取得するようにしてみます。結果はprintメソッドでターミナルに表示します。

ファイル selenium_test.py

from selenium import webdriver
from time import sleep
driver = webdriver.Chrome(executable_path="C:\Users\Aiueo\chromedriver.exe")

driver.get("https://www.google.co.jp")
sleep(3)
elem = driver.find_element_by_class_name("gLFyf")
elem.send_keys("PHP エンジニア")
sleep(3)
elem = driver.find_element_by_class_name("gNO89b")
elem.click()
sleep(5)

driver.get("https://www.google.co.jp")
sleep(3)
elem = driver.find_element_by_class_name("gLFyf")
elem.send_keys("Ruby エンジニア")
sleep(3)
elem = driver.find_element_by_class_name("gNO89b")
elem.click()

sleep(3)
elems = driver.find_elements_by_class_name("g")
for i in range(5):
    title = elems[i].find_element_by_class_name("LC20lb").find_element_by_tag_name
("span")
    print(title.text)
sleep(5)

driver.quit()

先ほどと同様に実行します。
$ python selenium_test.py
もしくは
$ python3 selenium_test.py

ターミナルの表示（一例）
Rubyエンジニアになるには｜未経験から就職・転職する方法 ...
Rubyエンジニアの仕事内容 - レバテックフリーランス
求人ボックス｜Ruby エンジニアの仕事・求人情報
Ruby エンジニアの求人 | Indeed (インディード)
Rubyエンジニアとは？未経験からRubyエンジニアになる方法 ...

(Ruby_input.png)
(Ruby_result.png)

検索結果のタイトルを一覧表示できました。
find_elements_by_class_name("クラス名")は、elementsと複数形になっています。同じクラス名の要素が複数あった場合に全て取得します。要素を1つ取り出す際には elems[0] のように番号を指定します。

1つ注意点があります。driver.getを用いると指定したURLへ移動できますが、for、while文の中で用いると繰り返しアクセスすることになります。コードの書き方を間違えると同じWebサイトに短時間に何度もアクセスしてしまい、不正アクセスとみなされてしまう可能性があるので、sleepなどを使って充分に時間を空けるようにして下さい。
（参考 https://ja.wikipedia.org/wiki/岡崎市立中央図書館事件）
また、WebサイトによってはSeleniumでアクセスできないように対策されている場合があります。その場合は仕方がないので諦めましょう。

ブラウザ自動化ツール「Selenium」の紹介でした。様々な場面で応用が効くと思うので、ぜひ使ってみて下さい。