0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Webドライバー不要】pydollでスクレイピングを試してみる

Last updated at Posted at 2025-04-21

0. はじめに

いつものようにXこと旧Twitterで情報を漁っていたら、pydollというスクレイピングライブラリを見つけましたので今回はこいつを動かしてみます

  • 動作環境
    ・ OS : Windows11 pro
    ・ python : 3.12.8
    ・ pydoll-python : 1.7.0
    ・ Jupyter Notebook(ipykernel)

1. pydollとは?

ブラウザ自動化といえば、SeleniumやPlaywrightなどが有名ですが、これらはWebDriverや外部バイナリの管理が煩雑で、非同期処理や人間らしい操作の再現に課題がありました。
Pydollは、WebDriverを使用せずに、Chromiumベースのブラウザを自動化するPythonライブラリです。

作者のredditを見つけましたが、スクレイピングしている時にCAPTCHAに苦しめられたそうで、その対策も入っているようです

2. pydollの実力を試してみる

導入は簡単 pip install pydoll-python

このライブラリはCAPTCHAに強いとのことなので、botチェッカーサイトで試してみることにする。

なおこのライブラリはPythonの非同期プログラミングに基づいた設計がされている為、async/await構文を使う必要があります。

pydollでbotチェッカーサイトにアクセスしてみる(練習.ipynb)
import re
import asyncio
from pydoll.browser.chrome import Chrome

# Jupyter Notebookで非同期関数を実行するための関数
import nest_asyncio
nest_asyncio.apply()

browser = None
page = None

async def start_browser():
    """ ブラウザを立ち上げる関数 """
    global browser, page
    if browser is None:  # まだブラウザが起動していない場合のみ実行
        browser = Chrome()
        await browser.start()
        page = await browser.get_page()
        print("ブラウザを起動しました")
    return browser, page


async def access_url(url):
    """ URLにアクセスする関数 """
    global browser, page
    
    # ブラウザがまだ起動していなければ起動
    if browser is None:
        await start_browser()
    
    # 指定されたURLに移動
    await page.go_to(url)
    print(f"{url}にアクセスしました")
    return page


async def get_text_by_css(css_selector):
    """ CSSセレクタ要素から文字を取得する関数 """
    global page
    try:
        # CSSセレクタで要素を取得
        element = await page.find_element(By.CSS_SELECTOR, css_selector)
        
        # 要素のテキストを取得
        try:
            # inner_htmlプロパティ
            text = await element.inner_html
            # HTMLタグを除去して純粋なテキストを返す
            clean_text = re.sub(r'<[^>]*>', '', text).strip()
            return clean_text
        except Exception as e:
            print(f"テキスト取得に失敗: {e}")
            return None
            
    except Exception as e:
        print(f"要素の取得に失敗: {e}")
        return None

async def close_browser():
    """ ブラウザを立ち下げる関数 """
    global browser
    if browser:
        await browser.stop()
        browser = None
        page = None
        print("ブラウザを終了しました")


# 最初にブラウザを起動
browser, page = await start_browser()

# URLにアクセス
url = "https://www.browserscan.net/bot-detection"
page = await access_url(url)

# 「Browser bot detection guide」の文字を取得
text_element = 'h1[class="_1tl1b6r"]'
text = await get_text_by_css(text_element)
print(f"要素:{text_element}に書かれている文字は{text}です")

# ブラウザを立ち下げる
await close_browser()
Jupyter出力
ブラウザを起動しました

https://www.browserscan.net/bot-detectionにアクセスしました

"要素:h1[class="_1tl1b6r"]に書かれている文字はBrowser bot detection guideです

ブラウザを終了しました

そして以下が実施にアクセスされたページであるが、Test Resultが「Normal」と書かれているので、このサイト基準ではこのアクセスはbotと見なされていないことになります

スクリーンショット 2025-04-21 210910.png

なお、同サイトにseleniumでアクセスすると以下のようになりました

selenium
from selenium import webdriver

driver = webdriver.Chrome()
driver.get("https://www.browserscan.net/bot-detection")

以下図のようにWebdriverが検知され、Botとして検知されていることがわかります。

スクリーンショット 2025-04-21 2131a29.png

3. おわりに

pydollを使うと、確かにwebdriverを使用せずに高速アクセスできることが確認できました。
このライブラリは今後個人的にも使っていこうと思います。

ただし悪用は厳禁であり、robots.txt等をしっかり調べた上で取得の際も相手に迷惑が掛からないように気を付けてスクレイピングしましょう

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?