MENU
  • ホーム
  • プログラミング
  • ワードプレス
    • プラグインプラグイン関連記事
    • 賢威賢威のカスタマイズ
    • CSSCSSの関連記事
  • サイト情報
    • プライバシーポリシー
  • ツール
    • メルエディター
    • フリマスパイダー – 疾風
    • フリマスパイダー
    • -ポイ活くんα-
  • お問い合わせ
あらゆるモノにHackする、探究者の読み物。
Let's Hack Tech
  • ホーム
  • プログラミング
  • ワードプレス
    • プラグインプラグイン関連記事
    • 賢威賢威のカスタマイズ
    • CSSCSSの関連記事
  • サイト情報
    • プライバシーポリシー
  • ツール
    • メルエディター
    • フリマスパイダー – 疾風
    • フリマスパイダー
    • -ポイ活くんα-
  • お問い合わせ
Let's Hack Tech
  • ホーム
  • プログラミング
  • ワードプレス
    • プラグインプラグイン関連記事
    • 賢威賢威のカスタマイズ
    • CSSCSSの関連記事
  • サイト情報
    • プライバシーポリシー
  • ツール
    • メルエディター
    • フリマスパイダー – 疾風
    • フリマスパイダー
    • -ポイ活くんα-
  • お問い合わせ
  1. ホーム
  2. プログラミング
  3. 言語別
  4. Python
  5. selenium×Chromeによるスクレイピング- Python

selenium×Chromeによるスクレイピング- Python

2023 2/02
Python
2019-07-04 2023-02-02
Google-Chrome
目次

seleniumとは

Pythonにはいくつかのスクレイピングライブラリがありますが、seleniumはその中でも、「ブラウザを操作する」タイプのライブラリです。

操作できるブラウザの種類も多く、ChromeやPhantomJS、FireFox、Edgeなどを自動操作することが出来ます。

操作するブラウザとして、以前は特別色々インストールせずともサクッと使いやすい PhantomJS が良く選ばれていたようですが、開発を終了したことや、そもそもクロームのシェアが高い事、Chromeが完全にヘッドレスに対応したこともあり、今ではChromeとの組み合わせで使うのが結構主流です。

selenium概要
  • ブラウザをマクロ的に自動操作できるライブラリ。
  • 本来はWebページのテスト用ツール。
  • データの取得・収集を目的とした、スクレイピングの用途にも使われる。
  • さまざまな種類のブラウザを操作可能。

seleniumでできる事

Pythonのスクレイピングライブラリとして非常にメジャーなhttpインターフェイスのrequestsと比較した場合、ブラウザ自動操作系のseleniumの最大の特徴としてJavaScriptの動作が挙げられます。

requestsなどのhttpリスエストのみを行うライブラリはJavaScriptによるサイトの内容の変化や、情報の展開を考慮することが出来ません。

JavaScriptによる動的な変化に対応したBot操作を行いたい場合はseleniumを選ぶことになるでしょう。

seleniumを使うメリット
  • JavaScriptによる動作を考慮したBotが作れる。
  • ログインの必要なページにも簡単にアクセスできる。

対して、デメリットとしてはJavaScriptなどによる実際のレンダリングエンジンが走るため、動作が遅い、且つ、クリックなどのメソッドは不安定になりがちです。

あと、超個人的な感想ですが、DOM操作系のメソッド記述がやたらダラダラと長ったらしいのも不満点だったりします。

純粋にスピードや安定感重視のBotを組みたいだけであれば、敢えてseleniumを選ぶメリットはありません。

seleniumを使うデメリット
  • ブラウザの描画処理があるので処理が遅い。
  • 動作は安定性に欠ける。
  • DOM操作系のメソッドの記述がやたらと長い。

seleniumのインストール

pip install selenium

pipで一発インストールできます。

Chrome Driver のインストール

seleniumのインストールだけではブラウザを操作することが出来ません。

ブラウザとseleniumの間に中継するドライバが必要なのでそれをインストールする必要があります。

FireFoxなど元々seleniumにドライバが組み込まれている一部ブラウザであれば、この操作は必要ありません。

今回はChromeを操作するためのドライバーをインストールしていきます。当たり前ですが、ドライバー単体では動作しませんのでChromeの本体インストールは必須です。

Chrome Driverのインストールに関しては環境によるところが大きいので、今回は一般的なWindows環境を前提とします。

Chrome Driverのダウンロード

こちらからダウンロード。

注意点として、インストール済みのChromeのバージョンとChromeDriverのバージョンを合わせてダウンロードする必要があります。

クロームのバージョン

Chrome Driverの設置

windowsのChrome Driver自体は一つの実行形式のexeファイルです。

任意のディレクトリに置いて、そのディレクトリにPathを通す必要があります。

seleniumでChromeを操作する

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

インポートして準備完了。

seleniumでChromeを立ち上げる

driver = webdriver.Chrome()

Chromeをヘッドレスで立ち上げる

#optionsインスタンスを生成
options = Options()
#オプションを設定
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-gpu')

#ドライバインスタンスを生成(Chromeの立ち上げ)
driver = webdriver.Chrome(options=options)

VBAでいうところの IE.Visible = False のようなバックグラウンド状態でクロームを操作できます。

‘–no-sandbox’ と ‘–disable-gpu’ は何なのかよく分かりませんが、これを指定しないと僕の環境ではエラーになります。環境によっては ‘–headless’ だけで動作する場合もあるみたいです。

任意のURLにアクセス

driver.get('https://www.yahoo.co.jp')

現在のURLを取得

driver.current_url

現在のページタイトルを取得

driver.title

ブラウザで表示中の全ソースを取得

driver.page_source

非常に個人的な感想ですが、単純にHTMLをパースするだけの使い方の場合は、selenuimはメソッドが長ったらしくてあまり好みではありません。

表示中のページソースを全て取得できるので、そのまま引き渡すことで、BeautifulSoupを使ったパースが可能になります。

from bs4 import BeautifulSoup as bs4

soup = bs4(driver.page_source, 'lxml')

ブラウザの更新

driver.refresh()

タブ(ウインドウ)を閉じる

driver.close()

現在アクティブのタブのみを閉じます。

全てのタブ(ウインドウ)を閉じる

driver.quit()

特定の要素を取得

driver.find_element_by_id('id_name') #idに該当する要素
driver.find_element_by_name('name') #nameに該当する最初の要素
driver.find_element_by_class_name('class_name') #classに該当する最初の要素
driver.find_element_by_link_text('link_text') #link textに該当する最初の要素
driver.find_element_by_tag_name('tag_name') #tagに該当する最初の要素
driver.find_element_by_css_selector('css') #cssセレクタに一致する最初の要素

指定した要素がpage_source内に存在しない場合は例外が発生する。

特定の要素を全て取得

driver.find_elements_by_id('id_name') #idに該当する全ての要素リスト
driver.find_elements_by_name('name') #nameに該当する全ての要素リスト
driver.find_elements_by_class_name('class_name') #classに該当する全ての要素リスト
driver.find_elements_by_link_text('link_text') #link textに該当する最初の要素
driver.find_elements_by_tag_name('tag_name') #tagに該当する全ての要素リスト
driver.find_elements_by_css_selector('css') #cssセレクタに一致する全ての要素リスト
driver.find_elements_by_xpath(".//a") #Xpathでも指定できます。

elementをelementsに変更するとリストで要素が返却されてきます。

idはページ内に1つしかないことが構文上の約束事ですが、seleniumではelementsとしても通ります。もちろんリストで返却されます。

要素が存在しない場合は例外ではなく、空のリストが返却されます。

要素が存在するかどうか確認する方法

[find_elements ~ ]では、該当する要素が存在しない場合は例外ではなく「空のリスト」が返却されてきますので、この性質を利用して、要素の存在を確認することが出来ます。

elm = driver.find_elements_by_id('id_name')
#存在しない場合空のリストがelmに格納される。

if elm:
   print('要素は存在する')
else:
   print('要素は存在しない')

特定の要素をクリック

ブラウザを操作することが出来るので、要素をクリックすることもできます。

driver.find_element_by_id('id_name').click()

特定の要素までスクロール

クリックメソッドですが、ウインドウ内に要素をとらえていない場合、上手く実行できないときがあります。

そういった場合、その要素の位置までスクロールする必要があります。

事前に ActionChains の import が必要です。

from selenium.webdriver.common.action_chains import ActionChains

element = driver.find_element_by_id("id_name")
actions = ActionChains(driver)
actions.move_to_element(element)
actions.perform()

特定の要素にテキストを入力

勿論、テキストを入力することも可能。ログインの操作などがrequestsと比べ楽に実装できます。ぶっちゃけ、これがselenium最大のメリット(使いどころ)だと個人的には思っています。

driver.find_element_by_id('id_name').send_keys('入力内容')

ちなみにエクセルのVBAによるIE操作と違って、NumLockされて変な感じになったり、OSで他の操作してたらsend_keysが失敗したりはしないので、安心して使えます。

テキスト以外のキーを入力

単純なテキスト入力ではなくキーボードのENTERやTABなどのキーを入力することもできます。事前に Keys の import が必要です。

from selenium.webdriver.common.keys import Keys

driver.find_element_by_id('id_name').send_keys('入力内容',Keys.TAB,Keys.ENTER)

send_keysに複数の引数を渡すと左から順に全てのkeyを送信します。

要素がウインドウ内に表示されているか

driver.find_element_by_id('id_name').is_displayed()

要素がアクティブかどうか

ボタンがグレーアウトして押せない場合などを判定できる。

driver.find_element_by_id('id_name').is_enabled()

要素が選択されているか

driver.find_element_by_id('id_name').is_selected()

ウインドウサイズの最大化

driver.maximize_window()
Pythonクローリング&スクレイピング[増補改訂版] -データ収集・解析のための実践開発ガイド
created by Rinker
技術評論社
¥3,608 (2023/03/26 21:29:14時点 Amazon調べ-詳細)
  • Kindle
  • Amazon
  • 楽天市場
  • Yahooショッピング

覚えておくと便利な小技

ChromeDriverのゴミインスタンスを一括kill

エクセルのVBAを使ったスクレイピングを書いている時なんかもアリがちなんですが、デバッグやらなんやらでコードを書いているうちに殺しきれなかったChrome Driverのインスタンスのゴミが大量にバックグラウンドに残っている時があります。

夢中になってコード書いてると、一面Chromedriver.exeで埋め尽くされていることなんかもあります。

seleniumの場合はほとんどありませんが、VBAの場合なんかだとメモリ圧迫されまくってIEが立ち上がらなくなってから気づくんですよね(笑)

Pythonならsubprocess モジュール使って直接殺していってもいいんですが、僕はbatファイルをあらかじめ作ってそれで一気にkillするようにしています。

@echo off
set APP_NAME=chromedriver.exe
for /f %%i in ('tasklist /fi "IMAGENAME eq %APP_NAME%" 2^>^&1') do (
    if /i %%i==%APP_NAME% (
        taskkill /im %APP_NAME% /f
        goto ENDLOOP;
    )
)
:ENDLOOP

一括でChromeDriverをkillできます。

selenium × Chrome によるログイン処理

requestsなどのHTTPの送受信のみを行うインターフェイスと違いブラウザの自動操作系のインターフェイスの利点の一つにログイン処理を楽に行えるという点があります。

そもそもJavaScriptによってBot判定がなされているサイトもあり、ブラウザ利用以外でのログインが難しい場合も多いです。

selenium を使ってChromeを操作すれば、それらの認証を通過して、ログインユーザーにしか扱えないページにBotアクセスすることが可能になります。

selenium × ChromeでYahoo!にログインする

ヤフーのログインフォームを入力するサンプルです。

from selenium import webdriver
import time

driver = webdriver.Chrome() #立ち上げ
driver.get('https://login.yahoo.co.jp/config/login') #ログインページへ

login_id = 'ログインid'
login_pass = 'ログインpass'

driver.find_element_by_css_selector('#username').send_keys(login_id) #id入力
driver.find_element_by_css_selector('#btnNext').click() #submitボタンをクリック
time.sleep(1)
driver.find_element_by_css_selector('#passwd').send_keys(login_pass) #passを入力
driver.find_element_by_css_selector('#btnSubmit').click() #submitボタンをクリック
time.sleep(1)

これでヤフーにログインした状態のブラウザの状態を作り出すことが出来ます。

一行ずつ追っていけば、普通のマクロ的な動作しかしていないので、割と簡単ですね。

ログイン状態を維持したまま操作をrequestsで行う

seleniumによるログイン処理は、普通にブラウザからアクセスするのと同じ操作をトレースすることで可能になりますので、非常に実装が楽になります。

ただ、情報を収集したり、変化を監視するといった用途のBotを組んでいく場合、seleniumは動作の速度や安定性に欠ける部分があります。

ブラウザの描画が必要な分、多少仕方ない部分ではありますが、ログイン処理後の動作にJavaScriptのエンジンが必要でない場合、その先をrequestsによって行うことが出来ます。

それぞれのライブラリに得意な部分のみを担当させるイメージです。

オススメの処理担当
  • ログイン処理 → selenium × Chrome
  • クロール処理→ requests × BeautifulSoup

HTTPと言うプロトコルは、一度のリクエストで完結し、前後の処理の相関を保持することが出来ません。簡単にいうと、一回ぽっきり。すぐに忘れます。つまり、HTTPはログインしたことなど、覚えていません。

では、何故ページをめくってWebサイトの中を回遊してもログイン状態が維持されているのか?というと、ログインセッションと言うのは基本的にCookieを使って管理されているからです。

Cookieと言うのはクライアント側(ブラウザ)に書き込まれる、メモ書きのようなもので、色々な用途に利用されますが、ログインの判定はその代表例です。

つまり、特定サイトにログインした状態のCookieがあり、尚且つ、そのCookieが有効期限内であれば、別のインターフェイスからそのサイトにアクセスしてもログイン状態を維持することが出来ます。

import requests

session = requests.session() #sessionインスタンスを作成

#Chrome Driverが持っているCookieを全てsessionに引き渡す
for cookie in driver.get_cookies(): 
   session.cookies.set(cookie["name"], cookie["value"])

session.get('login後操作したいURL')

上記処理で、seleniumでログインした状態のChromeブラウザのクッキーをrequestsのsessionインスタンスに引き渡すことが可能です。

その後はログインユーザー用のページをsession.get()で取得可能になります。

サイトの構造によっては使えないパターンもありますが、多くのサイトで使えるはずです。

seleniumでユーザープロファイルを指定してChromeを立ち上げる

ここまで、seleniumを用いてログインの必要なページを操作する処理を紹介してきました。

が、普段からChromeをメインのブラウザとして使っているのであれば、面倒なログインの処理なんかはすっ飛ばして、ログインした状態を作り出すことが出来る方法があります。

見出しにもある通り、Chromeに備わっている、ユーザープロファイルと言う機能をオプションとして指定することによって、普段使っている状態のChromeブラウザをそのまま操作することが可能になります。

以下でどういうことなのか詳しく説明していきます。

seleniumでChromeを立ち上げた時

まずはユーザープロファイルの指定をせずに、seleniumからChromeを立ち上げた場合の挙動を見ていきます。

from selenium import webdriver

driver = webdriver.Chrome()

ブックマークやユーザー名、拡張機能など、全てまっさらな状態で立ち上がります。

「Chrome は自動テスト ソフトウェアによって制御されています。」という、アラートも確認できます。

seleniumでユーザープロファイルを指定してChromeを立ち上げた時

次に、普段使っているChromeと全く同じ状態でseleniumから起動させる方法です。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
PROFILE_PATH = r'C:UsersUserNameAppDataLocalGoogleChromeUser Data'

driver = webdriver.Chrome(options=options)

seleniumを立ち上げたときの自動操作のメッセージが出ながらも、拡張機能やブックマークなどが表示されているのが確認できると思います。

ちなみにユーザープロファイルのパスは環境によって変わります。

ユーザープロファイルフォルダの確認方法
  • Chromeを起動する。
  • URLバーに chrome://version と入力して開く。
  • [プロフィール パス] の欄にパスが記述されているので確認する。

これでいつも使っている状態のChromeで自動操作を行うことが可能になります。

これで厄介な「reCAPTCHA」も突破しやすくなります。

突破しやすくなるというよりは、そもそもログインした状態を維持して立ち上げられます。(サイトやログイン方法によりますが。)

Pythonクローリング&スクレイピング[増補改訂版] -データ収集・解析のための実践開発ガイド
created by Rinker
技術評論社
¥3,608 (2023/03/26 21:29:14時点 Amazon調べ-詳細)
  • Kindle
  • Amazon
  • 楽天市場
  • Yahooショッピング
Python
Chrome selenium スクレイピング
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする コメントをキャンセル

email confirm*

post date*

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

シンプル美と機能性を両立させた、国内最高峰のWordPressテーマ『SWELL』
人気記事
  • IQテストいくつか受けてみました
    ネット上で信憑性がありそうなIQテスト、5種類まとめて受けた結果…
  • hayate
    メルカリの商品を世界最速で購入するためだけのアラートツール
  • 【Python】BeautifulSoupの使い方・基本メソッド一覧|スクレイピング
  • Pythonファイルのexe化
    【悲報】PyInstallerさん、300MBのexeファイルを吐き出すようになる
  • Amazon Echo アレクサのコマンドまとめ
    AmazonEchoの使い方とできる事、アレクサへの指示コマンド一覧
最近の投稿
  • PyQt5 QListWidget の item削除でtextBoxのフォーカスが奪われる2023-03-05
  • WordPressからのメールが届かない時の調査と解決法2023-02-27
  • 保護中: メルカリアラートツール「疾風」v22022-12-01
  • 保護中: メルカリアラートツール【疾風】カスタマイズオプション一覧2021-03-22
  • 保護中: メルカリアラートツール【疾風】インストール手順2021-03-22
目次
目次