【Pythonでwebスクレイピング】ログインが必要なサイトでスクレイピングを行う方法

Webスクレイピングの基礎2

前回はBeautiful Soup 4を使用したスクレイピング方法について紹介しました。Beautiful Soup 4はログイン不要なWebサイトのスクレイピングに適したライブラリとなっています。
今回は、ログイン処理までを行うスクレイピングに適しているライブラリであるSeleneについて紹介していきます。

1. Seleneについて

Selene とは?

Seleneは、SelenideというJava用のライブラリのPython用のラッパーです。
これらのライブラリはすべて、Webブラウザを自動操作させたUIテストツールを実現するものとして開発されてきました。
しかし、実際にはUIテストツールとしてではなく、Webスクレイピング目的としても非常に有用なライブラリとなっています。

Selene(Selenide)の用途

ログイン処理が必要な場合、もしくはJavaScriptを動作させたあとのページの状態でのスクレイピングの場合に効果を発揮するライブラリとなっています。

なお、Webブラウザを用いたWebスクレイピングの際には、古くからSeleniumというライブラリがよく使われていました。
しかし、近年ではそのSeleniumをさらに使いやすくしたSelenideがよく使われるようになってきています。
Selene(Selenide)はSeleniumよりも操作を非常に単純化させた仕組みになっていますので、これからWebクロールを学ぶ際は是非SeleniumよりもSelene(Selenide)を使用することをオススメします。

Selene(Selenide)を使うメリット

Seleniumを用いる場合、別途Chrome用、Firefox用のWeb Driverをダウンロードしてパスを通す必要がありました。
Selene(Selenide)を用いることで、必要なドライバは自動でダウンロードして使用できるようになります。
また、それ以外にも以下のような特徴があります。

  • 非常に簡潔で使いやすいAPI
  • Ajaxを介したページのテスト
  • 強力なセレクタ
  • 設定が非常にシンプルに変更可能

Selene のインストール

$ pip install selene --pre

Seleneについては、まだマイナーなパッケージのためcondaではまだインストールすることができません。pipを用いてインストールします。

2. SeleneでYahoo! ニュースの記事一覧を取得する

まずは、前記事と同様にヤフーニュースのスクレイピングをSeleneを用いて実装する例を紹介します。
コードは以下のようになります。

from selene.driver import SeleneDriver from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver import Chrome from selenium.webdriver.common.keys import Keys import time # ChromeのWebドライバを指定する。初回実行時はWebドライバがないはずなのでダウンロードが始まります。 driver = SeleneDriver.wrap(webdriver.Chrome(executable_path=ChromeDriverManager().install())) # Webブラウザで指定したURLを開く url = "https://news.yahoo.co.jp/" driver.get(url) # ニュース一覧をCSSセレクタで取得 news_elements_a_tag = driver.ss("#tpc_maj > ul > li > a") # ニュース一覧を出力する for a_tag in news_elements_a_tag: news_topic = a_tag.text.replace("NEW", "").replace("動画", "").strip() link_url = a_tag.get_attribute("href") print(news_topic + ", " + link_url) # Webブラウザがアクセスしてる様子が見えにくいと思いますのであえて10秒間スリープしています。 time.sleep(10) # 最後はdriverを終了させます(Webブラウザが閉じられる) driver.quit()

出力は以下のようになります

長距離巡航ミサイル 政府計画, https://news.yahoo.co.jp/pickup/6317373 明石市長選 前市長が当選確実, https://news.yahoo.co.jp/pickup/6317367 デサント 石本社長が退任へ, https://news.yahoo.co.jp/pickup/6317368 高さ5mの標識に車が突っ込む, https://news.yahoo.co.jp/pickup/6317363 「さくら味」ってつまり何味?, https://news.yahoo.co.jp/pickup/6317369 原監督 イチロー衰えていない, https://news.yahoo.co.jp/pickup/6317372 2児のママ 多忙な優木まおみ, https://news.yahoo.co.jp/pickup/6317371 水どうD 大泉洋と歩んだ23年, https://news.yahoo.co.jp/pickup/6317366

今回は、Google Chromeを用いたスクレイピングを示しています。
もしChromeがインストールされておらず、Firefox等のブラウザを使用している場合は以下のようにブラウザに合わせた設定に変更してください。

Firefoxの場合

from selenium.webdriver import firefox from webdriver_manager.firefox import GeckoDriverManager driver = SeleneDriver.wrap(webdriver.Firefox(executable_path=GeckoDriverManager().install()))

Edgeの場合

from selenium.webdriver import Edge from webdriver_manager.microsoft import EdgeDriverManager driver = SeleneDriver.wrap(webdriver.Edge(executable_path=EdgeDriverManager().install()))

これらのWebDriverは、初回コード実行時に自動的にダウンロードされます。
ダウンロード先は実行時にログで表示されているかと思います。
例えば、私のWindows 10の環境では、

C:\Users\ユーザ名\.wdm\chromedriver\2.46\win32/chromedriver.exe

に保存されました。

コードの詳細

Seleneの場合、driverという概念が重要になってきます。driverは現在起動中のWebブラウザ(Chrome)を操作するためのAPIが用意されています。
スクレイピングのためのHTMLの取得についても 現在表示中のWebブラウザ上のページ のデータ取得のみが可能ですので注意が必要です。

driver = SeleneDriver.wrap(webdriver.Chrome(executable_path=ChromeDriverManager().install()))

まずこの行ではdriverインスタンスを作成しています。このコードを実行すると、実際にGoogle Chromeが起動することがわかると思います。
これ以降、ここで起動されたChromeをプログラムで操作しつつデータを取得することになります。

driver.get("https://news.yahoo.co.jp/")

driver.get(URL)で、指定したURLにアクセスします。この行を実行するとWebブラウザ上で指定したURLのページが開かれます。
ここで注目して欲しいのは戻り値がないことです。

Beautiful Soup 4では、

soup = BeautifulSoup(news_html, 'html.parser')

のように、soup変数に結果を代入し、スクレイピング処理をしていました。

しかしSeleneでは、結果などの取得はすべてdriverという単一のインスタンスですべてを処理していくことになります。

news_elements_a_tag = driver.ss("#tpc_maj > ul > li > a")

この行では、CSSセレクタによりニュース記事一覧を取得しています。
driver.ss()関数では、現在表示中のページについてCSSセレクタにより欲しい情報を抽出できます。
CSSセレクタのについては前回の記事と全く同様の記法でOKです。
driver.s()という類似した関数がありますが、こちらは最初の一つ目の要素のみを取得します。
driver.ss()ではマッチしたタグをコレクション形式で返します。

# ニュース一覧を出力する for a_tag in news_elements_a_tag: news_topic = a_tag.text.replace("NEW", "").replace("動画", "").strip() link_url = a_tag.get_attribute("href") print(news_topic + ", " + link_url)

次にニュース一覧の出力部分の説明です。こちらは前回の記事とほぼ変わらないことがわかるかと思います。
a_tag.textでそのタグ以下にある文字列の取得が可能です。
a_tag.get_attribute("href")では現在のタグの指定した属性の内容を取得できます。ここではhrefタグの内容を取得しています。

driver.quit()

スクレイピング作業が終了しましたらdriver.quit()でWebブラウザを終了させましょう。

以上がニュース記事一覧の出力についての説明でした。
ご覧頂いたように、Webブラウザが実際に起動して操作をしている以外はBeautiful Soup 4とほぼ変わらないプログラムになっていることがわかるかと思います。
Seleneの本領が発揮されるのは次の章のフォーム操作からとなります。

3. Googleで検索フォームに文字列を入力して検索を実行する

この章ではSeleneの恩恵を受けることができる例を紹介します。
ここでは、Googleのトップページから検索クエリを入力し、検索ボタンを押して検索結果を取得するプログラムを示します。

from selene.driver import SeleneDriver from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver import Chrome from selenium.webdriver.common.keys import Keys import time driver = SeleneDriver.wrap(webdriver.Chrome(executable_path=ChromeDriverManager().install())) # Googleトップにアクセス driver.get("https://www.google.co.jp") # 入力フォームのタグを取得 input_form = driver.s("[name=q]") # 入力フォームに「Python Selene」と入力してEnterキーを押下 input_form.send_keys("Python Selene") input_form.send_keys(Keys.RETURN) # 検索結果のページの候補一覧のそれぞれのdiv要素を取得 div_list = driver.ss("div.g > div > div.rc > div.r") for div in div_list: title = div.s("h3").text link = div.s("a").get_attribute("href") print(title, link) # 例として検索結果の最初のリンク先のページへ飛んでみる driver.get(div_list[0].s("a").get_attribute("href")) time.sleep(10) driver.quit()

出力は以下のようになります

Selene : Python にも Selenide ライクな Selenium ラッパーあります - Qiita https://qiita.com/kobanyan/items/d75d3176038ee80d006f Python3+Selenium(Selene)+Chrome(headless)でMyDNS.jpを自動 ... https://qiita.com/toru2220/items/09bbb65c48b74b72a140 python seleneのCookie情報をrequestsに渡してアクセスする方法 - Qiita https://qiita.com/yhoriuc1/items/50b93d7886bf73b1a75d GitHub - yashaka/selene: Concise UI tests in Python + Ajax support + ... https://github.com/yashaka/selene Selene - Concise API for Selenium in Python — selene 1.0.0a11 ... https://selene.readthedocs.io/ Selenide Alternative in Python: Introducing Selene - Selenium Camp https://seleniumcamp.com/talk/selenide-alternative-in-python-introducing-selene/ はてなブックマーク - Selene : Python にも Selenide ライクな Selenium ... http://b.hatena.ne.jp/entry/s/qiita.com/kobanyan/items/d75d3176038ee80d006f selene · PyPI https://pypi.org/project/selene/ Python - python seleniumで新しいタブを開く方法。|teratail https://teratail.com/questions/117247

このプログラムのキモはもちろん入力フォームに文字列を入力し検索ボタンを押下→結果ページへの遷移の部分です。

# 入力フォームのタグを取得 input_form = driver.s("[name=q]")

まず、この部分ではGoogleのトップページの入力フォーム部分のタグをCSSセレクタで取得しています。

ここではinputタグのname=qの部分に注目してCSSセレクタを[name=q]としてタグを取得しました。

input_form.send_keys("Python Selene")

この部分で、先ほど取得したinputタグのテキストフォームにPython Seleneという文字を入力しています。
input_form.send_keysは、直感としてはそのタグにフォーカスを当てて、指定された文字列をキーボードで入力してるような動作をします。

input_form.send_keys(Keys.RETURN)

そして、次にその入力フォームでEnterキーを入力します。
普段我々がGoogleを使用する際、Googleの検索フォームでEnterキーを押すと、そのクエリの検索結果ページに推移すると思います。
Seleneを使用する際もそのときと同じ感覚でコーディングをしてあげるだけでOKです。

以上が入力フォームに文字列を入力し検索実行、検索結果ページに推移してデータを取得するコードとなります。

次はさらに発展して、ログイン処理を行うコードを書いてみましょう。

4. SeleneでTwitterのタイムラインを取得してみる

Seleneの醍醐味と言えばログイン処理まで可能なことです。
ここではTwitterへのログイン処理を行い、自分のアカウントのタイムラインを取得してみるプログラムを実装します。
もちろんTwitterはAPIがありますのでわざわざWebからのスクレイピングは不要ではありますが、今回は実例としてTwitterを使用します。

from selene.driver import SeleneDriver from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver import Chrome from selenium.webdriver.common.keys import Keys import time driver = SeleneDriver.wrap(webdriver.Chrome(executable_path=ChromeDriverManager().install())) # Twitterのログインページにアクセス driver.get("https://twitter.com/login") # 入力フォームのタグを取得 input_forms = driver.ss("div.clearfix.field input") user_name_form = input_forms[0] user_name_form.send_keys("ここにユーザID(ScreenName)") password_name_form = input_forms[1] password_name_form.send_keys("ここにパスワード") # エンターキーを押下してログイン password_name_form.send_keys(Keys.RETURN) time.sleep(10) driver.quit()

Googleの検索の例とほぼ同じなので詳しい説明は不要かと思います。

ログインページにアクセスし、CSSセレクタを用いてIDの入力欄のタグ、およびパスワードの入力欄のタグの取得を行っています。
そして、IDとパスワードを入力フォームにsend_keysで入力して、最後にEnterキーを押してログインを実行しています。

Webブラウザを見て無事ログインできていれば成功です!あとはご自由にデータを取得してみてください。
ここでは、直感的にわかりやすいようにTwitterの例を示してましたが、Twitter自体はWebスクレイピングを規約で禁止しています。
ですのでここではログインの方法のみを示させていただきました。
Twitterでは提供されているAPIでデータを取得するようにし、この例は使用しないようにご注意ください。

5. おわりに

いかがでしたでしょうか?
Seleneを使用することで、Web上での入力フォーム等を用いたページ遷移を介したプログラムを簡単に書くことができることがおわかりいただけたかと思います。
是非皆さんも様々なサイトでスクレイピングを実装して作業の時短を図ってみてはいかがでしょうか?
なお、一つだけ注意としてはTwitterのように規約で明確にスクレイピングを禁止しているようなサイトもあります。スクレイピングをする際は、規約などをしっかり読んでから行うように気をつけましょう。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です