Python自動化ライブラリ`DrissionPage`使用方法的な
はじめに
Pythonのブラウザ自動化ライブラリであるDrissionPageは、SeleniumとRequestsの機能を統合し、両者の利点を兼ね備えた強力なツールである。本記事は、DrissionPageの基本的な機能から応用的な使い方までを網羅的にまとめた備忘録である。
対象環境
- Python 3.8以上
- DrissionPage 4.0以上
DrissionPageとは
DrissionPageは、ブラウザの自動操作とWebページのデータ取得を一つのライブラリで完結させることを目的として開発された。Seleniumのようなブラウザ操作の容易さと、Requestsのような高速なHTTPリクエストの両方の利点を併せ持つ。特に、Shadow DOMの操作が容易である点や、タブ管理、WebPageとSessionPageの連携機能が強力である点が特徴である。
他のライブラリとの比較
| ライブラリ | 主な特徴 | DrissionPageとの違い |
|---|---|---|
| Selenium | ブラウザ自動化のデファクトスタンダード。多言語対応。 | DrissionPageはより直感的なセレクタ構文を持ち、HTTPリクエスト機能も内蔵している。 |
| Playwright | Microsoft製のモダンなライブラリ。非同期処理に強い。 | DrissionPageは学習コストが比較的低く、同期処理のスクリプトをシンプルに記述できる。 |
| Requests | HTTPリクエストに特化したライブラリ。非常に高速。 | DrissionPageのSessionPageはRequestsと同様の機能を提供するが、WebPageとの連携が最大の特徴である。 |
DrissionPageの最大の強みは、ブラウザ操作とAPIリクエストを同一のフレームワーク内でシームレスに切り替えられる点にある。
インストール
pipを使用してインストールする。
pip install DrissionPage
基本的な使い方
WebPageオブジェクトの初期化
WebPageクラスをインスタンス化することで、ブラウザ操作を開始する。
from DrissionPage import WebPage
# WebPageオブジェクトを作成(ブラウザが起動する)
page = WebPage()
初期化オプション
ChromiumOptions を使用して、ヘッドレスモード、プロキシ、ユーザーエージェントなどの起動オプションを細かく設定できる。
from DrissionPage import WebPage
from DrissionPage.common import ChromiumOptions
# 起動オプションを設定
co = ChromiumOptions()
co.set_headless(True) # ヘッドレスモードを有効化
co.set_user_agent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...') # ユーザーエージェントを設定
# co.set_proxy('http://user:pass@host:port') # プロキシを設定
# オプションを適用してWebPageオブジェクトを作成
page = WebPage(chromium_options=co)
設定ファイルによる管理
DrissionPage.iniというファイルをプロジェクトルートに配置することで、グローバルな設定を管理できる。これにより、コードの変更なしに動作を調整できる。
[paths]
# ブラウザの実行ファイルパス
browser_path = /path/to/your/chrome
[timeouts]
# グローバルなタイムアウト設定(秒)
base = 10
[chromium_options]
# デフォルトの起動引数
arguments = --start-maximized;--disable-infobars
ページへのアクセス
get()メソッドを使用して指定したURLにアクセスする。
from DrissionPage import WebPage
page = WebPage()
# 指定したURLにアクセス
page.get('https://www.google.com')
要素の取得
DrissionPageは、CSSセレクタやXPathなど、多彩な方法で要素を取得できる。独自のセレクタ構文も提供しており、直感的な記述が可能である。
DrissionPageのセレクタ構文
@は属性、|はOR条件、&&はAND条件、tag:はタグ名を示す。
# <div class="container" id="main">...</div>
# 以下のセレクタはすべて同じ要素を指す
ele1 = page.ele('.container@id=main')
ele2 = page.ele('tag:div@class=container@id=main')
ele3 = page.ele('@class=container&&@id=main')
単一要素の取得
ele()メソッドは、条件に一致する最初の要素を返す。
from DrissionPage import WebPage
page = WebPage()
page.get('https://www.google.com')
# DrissionPage構文で検索ボックスを取得
search_box = page.ele('tag:textarea@name=q')
複数要素の取得
eles()メソッドは、条件に一致する全ての要素をリストとして返す。
from DrissionPage import WebPage
page = WebPage()
page.get('https://www.google.com')
# ページ内の全てのリンクを取得
links = page.eles('tag:a')
for link in links:
print(f"Text: {link.text}, URL: {link.attr('href')}")
親・兄弟・子要素の取得
取得した要素から、parent() next() prev() child() などのメソッドで相対的な要素を取得できる。
# <body>
# <div>...</div>
# <p>Target</p>
# <a>...</a>
# </body>
p_tag = page.ele('tag:p')
div_tag = p_tag.prev() # 前の兄弟要素 (div)
a_tag = p_tag.next('tag:a') # 次の兄弟要素 (a)
body_tag = p_tag.parent() # 親要素 (body)
Shadow DOM内の要素取得
DrissionPageはShadow DOM内の要素を容易に取得できる。セレクタで :: を使用してShadow DOMの階層を辿る。
# <custom-element>
# #shadow-root
# <input type="text" id="inner-input">
# Shadow DOM内のinput要素を取得
inner_input = page.ele('custom-element::#inner-input')
inner_input.input('テキスト入力')
要素の操作
取得した要素に対して、クリックやテキスト入力などの操作を行う。
クリック
click()メソッドで要素をクリックする。
from DrissionPage import WebPage
import time
page = WebPage()
page.get('https://www.google.com')
# 検索ボックスにテキストを入力
search_box = page.ele('tag:textarea')
search_box.input('DrissionPage')
time.sleep(1) # 動作確認用
# 「Google検索」ボタンをクリック
search_button = page.ele('tag:input@value=Google 検索|@aria-label=Google 検索')
search_button.click()
テキスト入力
input()メソッドでテキストを入力する。clear=Trueで既存のテキストをクリアしてから入力する。
from DrissionPage import WebPage
page = WebPage()
page.get('https://www.google.com')
# 検索ボックスにテキストを入力
search_box = page.ele('tag:textarea')
search_box.input('DrissionPage', clear=True)
属性の取得・変更
attr()メソッドで属性値を取得し、set.attr()で属性値を変更できる。
from DrissionPage import WebPage
page = WebPage()
page.get('https://www.google.com')
# ロゴ画像のsrc属性を取得
logo = page.ele('tag:img')
logo_src = logo.attr('src')
print(f"Logo src: {logo_src}")
# 要素のstyle属性を変更して非表示にする
logo.set.attr('style', 'display: none;')
ページ操作
スクロール
scrollオブジェクトを使用してページをスクロールできる。
# ページ最下部までスクロール
page.scroll.to_bottom()
# 指定した要素が表示されるまでスクロール
element = page.ele('#footer')
element.scroll.into_view()
スクリーンショット
get_screenshot()メソッドでスクリーンショットを撮影できる。
# ページ全体のスクリーンショットを保存
page.get_screenshot(path='full_page.png', full_page=True)
# 特定の要素のみのスクリーンショットを保存
element = page.ele('tag:img')
element.get_screenshot(path='element_only.png')
JavaScriptの実行
run_js()メソッドでJavaScriptを実行し、その結果を取得できる。
# ページタイトルをJavaScriptで取得
title = page.run_js('return document.title;')
print(title)
# 引数を渡して実行
ua = page.run_js('return navigator.userAgent;')
print(ua)
待機処理
waitオブジェクトを使用して、特定の条件が満たされるまで待機する。動的なWebサイトを安定して操作するために不可欠である。
from DrissionPage import WebPage
page = WebPage()
page.get('https://www.google.com')
# 検索ボックスが表示されるまで最大5秒待機
search_box = page.wait.ele_displayed('tag:textarea', timeout=5)
search_box.input('Python')
# ページの読み込みが完了するまで待機 (load状態になるまで)
page.wait.page_load()
# 特定の要素がページから消えるまで待機
page.wait.ele_disappeared('div.loading-spinner')
iFrameの操作
get_frame()メソッドでiFrame要素を取得し、その中を操作できる。
from DrissionPage import WebPage
page = WebPage()
page.get('https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_iframe')
# idでiFrameを取得
iframe = page.get_frame('iframeResult')
# iFrame内の要素を操作
h1_text = iframe.ele('tag:h1').text
print(h1_text)
# メインページに戻る
page.to_main_frame()
タブの操作
new_tab()で新しいタブを開き、to_tab()でタブを切り替える。
from DrissionPage import WebPage
import time
page = WebPage()
page.get('https://www.google.com')
# 新しいタブで別のURLを開く
new_tab = page.new_tab('https://www.bing.com')
print(f"Current tab URL: {page.url}")
# 最初のタブに戻る
page.to_tab(page.tabs[0])
print(f"Switched back to: {page.url}")
# タブを閉じる (オブジェクトまたはインデックスを指定)
page.close_tab(new_tab)
time.sleep(2) # 動作確認用
page.quit()
高度な操作
アクションチェーン
actionsオブジェクトを使用して、マウスのホバーや右クリックなどの複雑な操作を行う。
from DrissionPage import WebPage
page = WebPage()
page.get('some_page_with_dropdown_menu')
# メニュー要素にマウスカーソルを合わせる
menu = page.ele('#menu')
page.actions.move_to(menu).perform()
# 表示されたサブメニューをクリック
submenu = page.ele('#submenu')
submenu.click()
エラーハンドリング
要素が見つからない場合など、例外処理を組み込むことでスクリプトの安定性を高めることができる。
from DrissionPage import WebPage
from DrissionPage.errors import ElementNotFoundError
page = WebPage()
page.get('https://www.google.com')
try:
# 存在しない要素を取得しようとする
non_existent_element = page.ele('#does-not-exist')
non_existent_element.click()
except ElementNotFoundError:
print("要素が見つからなかったため、処理をスキップしました。")
ファイルのダウンロードと管理
ChromiumOptionsでダウンロードパスを指定し、Downloaderオブジェクトで高度なダウンロード管理を行う。
from DrissionPage import WebPage
from DrissionPage.common import ChromiumOptions
import os
# ダウンロード設定
download_path = os.path.join(os.getcwd(), 'downloads')
co = ChromiumOptions().set_paths(download_path=download_path)
page = WebPage(chromium_options=co)
# ダウンロードマネージャを取得
downloader = page.get_downloader()
# ダウンロードを実行
url = 'https://www.python.org/ftp/python/3.12.3/python-3.12.3-amd64.exe'
downloader.download(url, rename='python_installer.exe')
# ダウンロードが完了するまで待機
# downloader.wait() # 全てのタスクが完了するまで待機
print(f"Download completed to: {download_path}")
page.quit()
WebPageとSessionPageの連携
DrissionPageの最も強力な機能の一つが、WebPageとSessionPageの連携である。WebPageでログイン処理などを行い、取得したCookieをSessionPageに引き継ぐことで、ブラウザを介さずに高速なAPIリクエストが可能になる。
from DrissionPage import WebPage, SessionPage
# --- WebPageでログイン ---
page = WebPage()
page.get('https://example.com/login')
page.ele('#username').input('user')
page.ele('#password').input('password')
page.ele('#login-button').click()
page.wait.url_changes() # ログイン後のページに遷移するのを待つ
# --- Cookieを取得してSessionPageに渡す ---
cookies = page.get_cookies()
# ブラウザを閉じる
page.quit()
# --- SessionPageでAPIアクセス ---
s_page = SessionPage()
s_page.set_cookies(cookies)
# ログインが必要なAPIエンドポイントにアクセス
s_page.get('https://example.com/api/user/profile')
# 取得したデータを表示
print(s_page.json)
SessionPageによる高速リクエスト
SessionPageは、ブラウザを起動せずにRequestsライブラリのようにHTTPリクエストを送信する。ブラウザ操作が不要なデータ取得に非常に高速である。
from DrissionPage import SessionPage
# SessionPageオブジェクトを作成
s_page = SessionPage()
# getリクエスト
s_page.get('https://api.github.com/events')
# レスポンスをJSONとして取得
json_data = s_page.json
print(json_data[0]['id'])
# postリクエスト
data = {'key': 'value'}
s_page.post('http://httpbin.org/post', data=data)
print(s_page.json['form'])
実践的なデータ抽出
スクレイピングの一般的なタスクは、Webページから構造化されたデータを抽出することである。eles()で取得した要素リストをループ処理することで、これを実現できる。
from DrissionPage import WebPage
import json
page = WebPage()
# 架空の商品リストページにアクセス
page.get('https://example.com/products')
product_list = []
# 各商品カード要素を取得
product_cards = page.eles('.product-card')
for card in product_cards:
# 各カード内から情報を抽出
name = card.ele('.product-name').text
price = card.ele('.product-price').text
url = card.ele('tag:a').attr('href')
product_list.append({
'name': name,
'price': price,
'url': url
})
# 抽出したデータをJSON形式で出力
print(json.dumps(product_list, indent=2, ensure_ascii=False))
ベストプラクティスとパフォーマンス
- WebPageとSessionPageの使い分け:
WebPageはJavaScriptが多用されるページの操作や初回ログインに用い、それ以降のデータ取得はCookieを引き継いだSessionPageで行うことで、処理を大幅に高速化できる。 - 明示的な待機の使用:
time.sleep()のような固定時間の待機は、必要以上に待機したり、待機時間が足りなかったりする場合がある。page.wait.ele_displayed()など、特定の条件を満たすまで待機する明示的な待機を使用することで、スクリプトの安定性と速度が向上する。 - 効率的なセレクタ:
id属性など、一意で高速に特定できるセレクタを優先的に使用する。複雑なXPathやCSSセレクタは、ページの構造変更に弱く、パフォーマンスも低下する傾向がある。 - ヘッドレスモードの活用: UIの描画が不要なため、特にサーバーサイドでの定期実行などでは、ヘッドレスモードを使用することでリソース消費を抑え、高速に動作する。
- リソースの解放: スクリプトの最後で
page.quit()を呼び出し、ブラウザプロセスを確実に終了させる。
おわりに
DrissionPageは、Seleniumの直感的なブラウザ操作とRequestsの高速なリクエスト処理を融合させた、非常に効率的で高機能なライブラリである。特に、WebPageとSessionPageの連携は、自動化やスクレイピングの可能性を大きく広げる。本記事で紹介した機能は多岐にわたるが、これらはDrissionPageの能力の一部に過ぎない。より詳細な情報や、最新の機能については、公式のドキュメントを参照されたい。
Discussion