Python入門
第26回.WEBスクレイピング(selenium)

Pythonの初心者向け入門解説、人気のプログラミング言語Python
最終更新日:2020-10-11

第26回.WEBスクレイピング(selenium)


Python WEBスクレイピング selenium

PythonでWEBスクレイピングをします。
これにはいろいろな方法がありますが、定番ともいえるseleniumを使います。
seleniumを使う事で、WEBスクレイピングがとても簡単に行う事ができるようになります。


VBAでもSeleniumが使えるので以下で紹介しています。

VBAのスクレイピングを簡単楽にしてくれるSelenium
VBAでWebスクレイピングする方法としてIE自動操作がありますが、VBA記述が結構面倒になります、もっと簡単にスマートにVBAを書きたいと思ったら…SeleniumBasicを使ってみましょう。SeleniumBasicは、エクセルVBAでのWeb閲覧を自動化することを強力かつ簡単に実現してくれます。

VBAで紹介したものとほぼ同じ内容にしていますので、見比べると違いが良く分かるかもしれません。



目次

seleniumについて

Seleniumは、 C#、Java、Perl、PHP、Python、Ruby等々の一般的なプログラミング言語が提供されています。
Seleniumはブラウザを自動化します。
何をするかは完全にあなた次第です。
主にテスト目的でWebアプリケーションを自動化するためのものですが、これに限定されるものではありません。
退屈なWebベースの管理タスクも自動化できます。

公式サイト - SeleniumHQ Browser Automation

公式ではありませんが、メソッドを調べたりするには以下がとても使いやすいと思います。
Seleniumクイックリファレンス
特に逆引きが便利です。


seleniumのインストール

ライブラリのインストール

pipを使ってopenpyxlをインストールします。

pip install selenium

ライブラリのインストールについての詳細は以下を参照してください。

ドライバーのインストール

操作するブラウザのドライバが必要です。

chrome
chromeのバージョンを確認しておいてください。
Python WEBスクレイピング selenium

Python WEBスクレイピング selenium

Python WEBスクレイピング selenium

pip install chromedriver-binary

インストールされたバージョンを確認します。

Python WEBスクレイピング selenium

一致しているので問題なかったようです。
通常は自動で最新版になっているはずなので、これで良いはずです。
もし、バージョンが古い場合は、バージョン指定でインストールできるようですが、公開されているバージョンが存在しているかは確認が必要です。

pip install chromedriver-binary==86.0.4240.22.0
現時点のバージョンです。
pip install chromedriver-binary Release history

使用しているchromeのバージョンと同一のものがない場合は、その直前のバージョンをインストールすれば良いはずです。

Visual Studioで入れるとバージョンを直ぐに見ることができます。

Python WEBスクレイピング selenium

Edge
本記事作成にあたって調べているときに、Windowsのアプリと機能で入れればよいという情報もありましたが違うようです。

Edgeのバージョンを確認しておいてください。
Python WEBスクレイピング selenium

Python WEBスクレイピング selenium

Python WEBスクレイピング selenium

以下よりドライバーをダウンロードしてください。
WebDriver - Microsoft Edge Developer

Python WEBスクレイピング selenium

環境に合わせてダウンロードしてください。
zipを点かいすると、
msedgedriver.exe
これをパスの通ったフォルダに入れてください。
別途にパスを通しても良いとは思いますが、筆者はWindows10(64bit)ですが以下にしました。

Python WEBスクレイピング selenium

公式ドキュメントは以下になります。
テストオートメーションに WebDriver (Chromium) を使用する
WebDriver (Chromium) - Microsoft Edge Development | Microsoft Docs


WEBサイトを表示してみましょう

何はともあれ、お決まりのヤホーを表示してみましょう。
スクリプトが終了するとブラウザが閉じてしまうので、画面を確認できる程度にsleepさせています。
これには、timeモジュールを使っています。

chrome

import time
from selenium import webdriver
import chromedriver_binary #パスを通すのに必要
driver = webdriver.Chrome() driver.get("https://www.yahoo.co.jp/") time.sleep(5) driver.quit()

Edge

import time
from selenium import webdriver
driver = webdriver.Edge(executable_path="msedgedriver.exe") driver.get("https://www.yahoo.co.jp/") time.sleep(5) driver.quit()
WEBのサンプルでは、msedgedriver.exeこれをフルパスで指定しているものがほとんどでしたが、パスが通っていれば問題ありません。

quit()が無くてもスクリプトが終了すればブラウザは閉じられます。

これ以降は、chromeのコードのみ掲載します。
上記の通り最初部分だけの違いで、その他は基本的には同様になります。


Seleniumの基本的な使い方(株価情報を取得してみる)

Yahooを表示したので、
「経済」タブの「日経平均株価」を取得してみましょう。

取得するには、そもそもページ全体の中から、取得したいデータの場所を特定しなければなりません。
WEBページはHTMLで作成されています。
どの要素(element)を取得するかをseleniumに指定しなければなりません。
WEBページのソースをみてHTMLタグ等からだけでは必要な情報(element)がどれかを探すのは大変だったり、たどり着けなかったりします。

Chromeのデベロッパーツールを使用します。

Python WEBスクレイピング selenium

「Google Chrome の設定」→「その他のツール」→「デベロッパー ツール」
ショートカットは、F12

Python WEBスクレイピング selenium

「デベロッパー ツール」の表示位置は、以下のアイコンで変更できます。

Python WEBスクレイピング selenium

下または右にするのが普通でしょうか。
では、まずはこれを使って、Yahooの「経済タブ」の要素を特定します。

Python WEBスクレイピング selenium

このアイコンをクリックすると、要素(element)の選択モードになります。
element選択モードを解除するには、もう一度このアイコンをクリックしてください。
WEBページ内をクリックしても選択モードは解除されます。

element選択モードで、マウスカーソルをWEBページ内で移動すると、

Python WEBスクレイピング selenium

このように、カーソル下が色付けされて表示されるのが分かるようになっています。
適当にカーソルを動かしてみて、色付けされている範囲が変更されることを確認してください。
この色付けされている範囲が、ページを構成している要素(element)になります。

このエレメントは入れ子になっていて、
エレメントの中にエレメントがあり、そのエレメントの中にもさらにエレメントが入っている作りになっています。

上図のように、「経済」が選択された状態でクリックすると、
「デベロッパー ツール」内の該当箇所が選択されます。

Python WEBスクレイピング selenium

今度は、「デベロッパー ツール」内でマウスを移動させてみてください。
「デベロッパー ツール」のマウスカーソル位置に該当するWEBページの当該箇所が色付けされます。

element選択モードで、WEBページ内から目的の箇所を探したり、
デベロッパー ツール内の選択から目的の箇所を探したりと、双方向で探すことができます。

目的のエレメントに到達したら、デベロッパー ツールのelementを右クリックします。

Python WEBスクレイピング selenium

そして、「Copy」から「Copy selecter」をクリックしてください。

Python WEBスクレイピング selenium

クリップボードに、CSSセレクターが入ります。

「経済」タブは、
#tabTopics2 > a
とコピーされたはずです。
※これはYahooがたまに更するので、過去は違いましたし今後も変更されます。

これを使って、seleniumで「経済」タブをクリックしてみましょう。
前出のコードに追記します。

Python WEBスクレイピング selenium

エレメントを見つけるので、find_element_by_○○というメソッドになります。

find_element_by_class_name
find_element_by_css_selector
find_element_by_id
find_element_by_link_text
find_element_by_name
find_element_by_partial_link_text
find_element_by_tag_name
find_element_by_xpath

いろいろなメソッドが用意されていることを確認しておきましょう。
どれを使うかは、その時々で変わってきますが、
今回は、CSSセレクターなので、
find_element_by_css_selector
これになります。
この引数に先ほどCopyしたCSSを入れます。
そして、それをクリックなので、.click()メソッドを続けます。
import time
from selenium import webdriver
import chromedriver_binary
driver = webdriver.Chrome()
driver.get("https://www.yahoo.co.jp/")
driver.find_element_by_css_selector("#tabTopics2 > a").click()
time.sleep(5)
elementは適宜変数に入れてから使ってください。
import time
from selenium import webdriver
import chromedriver_binary
driver = webdriver.Chrome()
driver.get("https://www.yahoo.co.jp/")
elm = driver.find_element_by_css_selector("#tabTopics2 > a")
elm.click()
time.sleep(5)

これで「経済」タブが表示されたので、次は「日経平均株価」です。

Python WEBスクレイピング selenium

クリック→elementを右クリック→Copy selector
#tabpanelTopics2 > div > div:nth-child(2) > div > div > a:nth-child(1) > div._1MotBVaN8-ZbqGA2Wc3v-R > span > span._1Cr2FsRZgNQlia2CFSRBBG
これがコピーされますので、これを使って、

from selenium import webdriver
import chromedriver_binary
driver = webdriver.Chrome()
driver.get("https://www.yahoo.co.jp/")
driver.find_element_by_css_selector("#tabTopics2 > a").click()
elm = driver.find_element_by_css_selector("#tabpanelTopics2 > div > div:nth-child(2) > div > div > a:nth-child(1) > div._1MotBVaN8-ZbqGA2Wc3v-R > span > span._1Cr2FsRZgNQlia2CFSRBBG")
print(elm.text)
driver.quit()
なんとんなく分かると思いますが、文字列を取得するのでtextを使います。

Python WEBスクレイピング selenium

このように出力されます。
(当たり前すぎますが、株価は実行日によって変わりますよ。)

上記ではコピーしたcss selectorをそのまま使いましたが、要素が確定出来れば最後の部分だけで構いません。
elm = driver.find_element_by_css_selector("span._1Cr2FsRZgNQlia2CFSRBBG")


色々なパターンでのseleniumの使い方

画面最大化

driver.maximize_window()
ブラウザで見えていないエレメントにはアクセスできないページもあるので、
最大化しておいた方がとりあえずは扱いやすいと思います。

Wait処理

import time
#・・・
time.sleep(5)
Seleniumは、画面が表示されるまで自動で待ってから戻ってくるので、ページロード待ちはあまり気にする必要がないはずなのですが、
ですが、それだけでは対応できないページもあります、といいますか、結構多いです。
そこで、ページによっては明示的にwaitを入れる必要が出てきます。

必要なエレメントが見つかるまでループさせる方法にしたほうが良いのですが、
単純に、1~3秒程度待たせてしまったほうが、VBA自体は簡単になります。

テキストボックスに文字を入れる

from selenium import webdriver
import chromedriver_binary
import time
driver = webdriver.Chrome() driver.get("https://www.google.com/") elm = driver.find_element_by_name("q") elm.clear() elm.send_keys('エクセルの神髄') elm.submit()
ここではVBAサンプルとして、Googleで「エクセルの神髄」を検索しています。

エレメントをオブジェクト変数にセットするようにしています。
文字列の送信は、send_keysになりますが、
既に文字が入っている場合はその後ろに入ってしまうので一旦clearするようにしています。

ドロップダウン(プルダウン)メニューの選択

from selenium.webdriver.support.ui import Select
#・・・
elm = driver.find_element_by_id("hoge")
sel_elm = Select(elm)
sel_elm.select_by_value("fuga")
selenium.webdriver.support.uiのSelectを使います。
Selectには、以下の3種類があるので適宜使い分けてください。

select_by_index
select_by_value
select_by_visible_text

上記は変数に入れて1回ずつ処理していますが、ネストしても構いません。
ただし、別々にしておいた方がテストしやすいですし、保守しやすいと思います。
find_element_byは適宜css等と使い分けてください。

オプションの一覧の取得
elm = driver.find_element_by_id("foge")
sel_elm = Select(elm)
for option in sel_elm.options:
    value = option.get_attribute('value')
    text = option.text
    print(f"{value=}{text=}")
ドロップダウンのオプションの一覧が出力されます。

フレームを切り替える

iframeタグが使われているページの場合、各iframe内の要素にはそのままではアクセスできません。

iframeは「inline frame」の略で、インラインのフレームを作成するためのタグです。
HTMLは以下のようなものになります。
<iframe id="identiFier" src="https://・・・">

iframe内の要素にアクセスするには、その前に当該のiframeに切替てから行います。
iframe = driver.find_element_by_id("identiFier")
driver.switch_to.frame(iframe)
print(driver.find_element_by_tag_name("hoge").text)
iframe内に切り替えた後は、普通にfindで扱えます。

WEBサイトの操作は、マウスクリックとキーボード入力で全て操作できます。
従って基本としては、clickとsend_keysで操作することになりますが、seleniumで操作するときにいくつか専用の使い方が必要なものがあります。


色々組み合わせて目的の画面にたどり着きます

Yahooで以下の操作を行います。
「経済」→「日経平均株価」→「銘柄コード」に4689→「検索」→「アラート設定」
→「ID」入力→「次へ」→「パスワード」入力→「次へ」→「値上がり率」に15%
import time
from selenium import webdriver
import chromedriver_binary
from selenium.webdriver.support.ui import Select
def wait_for_element(a_driver, kind, a_str, max_cnt=10): for n in range(max_cnt): try: #とりあえず必要なもののみ入れました。 if kind == "css": elm = a_driver.find_element_by_css_selector(a_str) elif kind == "id": elm = a_driver.find_element_by_id(a_str) elif kind == "name": elm = a_driver.find_element_by_name(a_str) elif kind == "link": elm = a_driver.find_element_by_link_text(a_str) else: raise ValueError("パラメーター不正") except: time.sleep(1) else: return elm raise ValueError(f"{kind}:{a_css}:要素が見つかりません。")
def wait_for_sendkeys(a_elm, a_str, max_cnt=10): for n in range(max_cnt): try: a_elm.clear() a_elm.send_keys(a_str) except: time.sleep(1) else: return raise ValueError(f"send_keys:{a_str} テキストを送れませんでした。")
driver = webdriver.Chrome() driver.get("https://www.yahoo.co.jp/")
#「経済」 driver.find_element_by_css_selector("#tabTopics2 > a").click()
#「日経平均株価」 driver.find_element_by_css_selector("span._1Cr2FsRZgNQlia2CFSRBBG").click()
#「銘柄コード」 elm = wait_for_element(driver, "id", "searchText") wait_for_sendkeys(elm, "4689")
#「株価検索」 driver.find_element_by_id("searchButton").click()
#「アラート」 wait_for_element(driver, "link", "アラート設定").click()
#「ID」入力 elm = wait_for_element(driver, "name", "login") wait_for_sendkeys(elm, "IDを指定")
#「次へ」 wait_for_element(driver, "name", "btnNext").click()
#「パスワード」入力:そのまま続けるとエラーとなるのでWait対応<br> elm = wait_for_element(driver, "id", "passwd") wait_for_sendkeys(elm, "パスワードを指定")
#「次へ」 wait_for_element(driver, "css", "#btnSubmit > span").click()
#「値上がり率」を15% elm = wait_for_element(driver, "id", "up_0") sel_elm = Select(elm) sel_elm.select_by_value("15")
#登録しても仕方ないので、画面を見て確認してください。 time.sleep(30)
Seleniumでブラウザを起動すると、クッキー等は全て無効になっているので画面によっては、通常操作では必要ないログインを求められます。

Yahooのこのページでは、例えばパスワード入力ではそのままではエラーとなってしまう等の注意が必要です。
上記ではサンプルの意味も兼ねて、エレメントへの設定が正しく行われるまで繰り返す関数を作成しています。
wait_for_element
wait_for_sendkeys

最後のドロップダウンのoptionを確認する場合は、
デベロッパーツールで、ドロップダウンをクリック後に、

Python WEBスクレイピング selenium

"down_0>…</select>この…をダブルクリッククリックすると、optionの中が展開されます。

Python WEBスクレイピング selenium


elementをコレクションで取得する

tdタグやliタグのように、同一タグの繰り返しを順次処理する場合は、
指定タグのエレメントをコレクションで取得し、イテレーターで処理します。

以下では、Yahooのトピック一覧を取得しています。
from selenium import webdriver
import chromedriver_binary
driver = webdriver.Chrome() driver.get("https://yahoo.co.jp") elms = driver.find_element_by_css_selector("#tabpanelTopics1") for elm in elms.find_elements_by_tag_name("h1"): print(elm.text)
find_element系メソッドには、オブジェクト単体の取得とコレクションの取得が用意されています。
find_elementとfind_elementsが存在します。
コレクションとして取得する場合は、find_elementsを使用します。

find_elements_by_class_name
find_elements_by_css_selector
find_elements_by_id
find_elements_by_link_text
find_elements_by_name
find_elements_by_partial_link_text
find_elements_by_tag_name
find_elements_by_xpath


新規ページが開かれる場合

クリックによって新規ページが開かれるような場合、新規ページへ移動する必要があります。
まずは特に何もしない場合の動作状況になります。
from selenium import webdriver
import chromedriver_binary
driver = webdriver.Chrome() driver.get("https://excel-ubara.com/python/python025.html") driver.find_element_by_link_text("第24回.エクセルを操作する(openpyxl)") elm = driver.find_element_by_tag_name("h1") print(elm.text) driver.quit()
これでprintで出力されるのは、
「Python入門
第25回.エクセルを操作する(pywin32:win32com)」
このように、クリックする前の元のページのh1が取得されてしまいます。
そこで、次ページへ移動する記述を入れる必要があります。
from selenium import webdriver
import chromedriver_binary
driver = webdriver.Chrome() driver.get("https://excel-ubara.com/python/python025.html") driver.find_element_by_link_text("第24回.エクセルを操作する(openpyxl)") whandles = driver.window_handles driver.switch_to.window(whandles[-1]) elm = driver.find_element_by_tag_name("h1") print(elm.text) driver.quit()
これでprintでは、以下のように出力されます。
「Python入門
第24回.エクセルを操作する(openpyxl)」

window_handlesは配列になっています。
新しいウィンドは後ろに追加されるので[-1]は最後のウィンドウになります。
もちろん、[0]から[-1]までの任意のウィンドウに切り替えるることができます。


上手くいかない特殊な場合の対処方法

実際のWEBページは多種多様で、ここまでの対処できない場合が多々あります。
そのような場合は、個別の対処方法を考える必要があります。
以下に代表的な対処方法の例を載せておきます。
あくまで一例ですので、個別に工夫してお使いください。

driverやtimeはimportされているものとしています。

テキストボックスに1回で文字列を入れられない場合

def sendkeys_textbox(a_driver, a_css, a_str, max_cnt=10):
    for n in range(max_cnt):
        elm = a_driver.find_element_by_css_selector(a_css)
        elm.clear()
        elm.send_keys(a_str)
        if elm.get_attribute('value') == a_str:
            return True
        time.sleep(1)
    return False

クリック後に新ページ移動前にseleniumから戻ってきてしまう場合

def click_newpage(a_driver, a_css, max_cnt=10):
    old_url = a_driver.current_url
    for n in range(max_cnt):
        a_driver.find_element_by_css_selector(a_css).click()
        if a_driver.current_url != old_url:
            return True
        time.sleep(1)
    return False

画面ロード完了前にseleniumから戻ってきてしまう場合

def exist_element(a_driver, a_css, max_cnt=10):
    for n in range(max_cnt):
        elms = a_driver.find_elements_by_css_selector(a_css)
        if len(elms) > 0:
            return True
        time.sleep(1)
    return False

遷移後のURLに直接移動する

driver.get(a_driver.current_url + "?xxx&yyy")
最後の手段になりますが、遷移後のURLに移動してしまう方法も有効です。
クリック後にURLパラメーターが追加になるような場合は、直接パラメーターを追加したURLを指定してしまう方法になります。

元々のURLの最後が"/"で終わっているか、既に"?"が入っているか、
これらの状態によって、追加するパラメーターは適宜変更が必要になります。

URLパラメーター
URLに付け加える変数です。
クエスチョンマーク"?"をURLの末尾に付け、「変数(パラメータ)=値」の形式で指定します。
複数のパラメーターはアンパサンド(&)でつなげます。




同じテーマ「Python入門」の記事

第16回.Pythonの引数は参照渡しだが・・・
第17回.リスト内包表記
第18回.例外処理(try文)とexception一覧
第19回.import文(パッケージ・モジュールのインポート)
第20回.フォルダとファイルの一覧を取得(os,glob,pathlib)
第21回.CSV読み込みとopen()関数とwith文
第22回.CSV読み書き(csvモジュール)
第23回.pipコマンド(外部ライブラリのインストール)
第24回.エクセルを操作する(openpyxl)
第25回.エクセルを操作する(pywin32:win32com)
第26回.WEBスクレイピング(selenium)


新着記事NEW ・・・新着記事一覧を見る

WEBスクレイピング(selenium)|Python入門(10月11日)
エクセルを操作する(pywin32:win32com)|Python入門(10月5日)
エクセルを操作する(openpyxl)|Python入門(10月3日)
pipコマンド(外部ライブラリのインストール)|Python入門(10月1日)
CSV読み書き(csvモジュール)|Python入門(9月29日)
「Excel 4.0 マクロ」の使い方|VBA技術解説(9月28日)
CSV読み込みとopen()関数とwith文|Python入門(9月28日)
フォルダとファイルの一覧を取得(os,glob,pathlib)|Python入門(9月26日)
import文(パッケージ・モジュールのインポート)|Python入門(9月24日)
例外処理(try文)とexception一覧|Python入門(9月23日)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
5.マクロって何?VBAって何?|VBA入門
6.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
7.繰り返し処理(For Next)|VBA入門
8.セルに文字を入れるとは(Range,Value)|VBA入門
9.とにかく書いてみよう(Sub,End Sub)|VBA入門
10.マクロはどこに書くの(VBEの起動)|VBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。



このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ