新しいことにはウェルカム

技術 | 電子工作 | ガジェット | ゲーム のメモ書き

Selenium と Playwright の両方を使ってみた感想

WebのクローリングにPuppeteerを使っています。

いつかPuppeteerの使い方をまとめたいなと思っていたのですが、そうこうしている内に月日は流れ、Puppeteerと同様のブラウザ操作ツールとして、Playwrightの名前をよく聞くようになってきました。

ならばいっそのこと、新たにクローラーを書く時はPlaywrightに乗り換えて、その使い方をまとめようかなと思い始めました。

一方、ブラウザ操作ツールとしてSeleniumも有名です。

Microsoft Power AutomateでSeleniumが使えると聞いたので、Seleniumならクローリングだけでなく、日々の業務の自動化にも使えて便利かなとSeleniumにも興味がありました。

SeleniumとPlaywright、どちらにしようかと迷ったのですが、どちらも使ったことがなかったので結局両方を使って確かめることにしました。

ここでは、そのSeleniumとPlaywrightの両方を使ってみた感想を書きたいと思います。

仕組み

Selenium

ブラウザを外部から操作する方法として、WebDriverというAPI規格がW3Cで決まっています。

SeleniumはWebDriverを使ってブラウザを操作します。

SafariはWebDriverの機能を持っているので、Seleniumから直接操作することができるのですが、他のブラウザはWebDriverの機能を持っておらず、その場合、各ブラウザ専用のWebDriverアプリが別に用意されているのでインストールします。

SeleniumはインストールしたWebDriverアプリを操作します。そして、WebDriverアプリがブラウザを操作することにより、間接的にSeleniumからブラウザを操作します。

Playwright

Chrome系のブラウザには、外部から操作・通信するためのプロトコルが実装されています。PlaywrightやPuppeteerは、そのプロトコルを使いやすくするためのライブラリで、そのプロトコルを使ってブラウザを直接操作します。

プログラム例

Googleで「test」を検索し、4ページ目の結果のソースを取得するプログラムを、SeleniumとPlaywrightで書いてみます。

Selenium

from selenium import webdriver
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager

driver = webdriver.Chrome(ChromeDriverManager().install())

driver.get("https://www.google.com")

elem = driver.find_element(By.CSS_SELECTOR, "form input[name=q]")
elem.send_keys("test\n")

elems = driver.find_elements(By.CSS_SELECTOR, "div[role=navigation] table td a")
elems[3].click()

print(driver.page_source)

driver.quit()

Playwright

import { chromium } from 'playwright';

(async () => {
    try {
        const browser = await chromium.launch({
            headless: false,
        });
        const context = await browser.newContext();
        const page = await context.newPage();

        await page.goto("https://www.google.com");

        await page.type("form input[name=q]", "test\n");

        let elems = page.locator("div[role=navigation] table td a");
        await elems.nth(3).click()

        console.log(await page.content());

        await browser.close();

    } catch (err) {
        console.error(err);
    }
})();

両者とも似たような感じです。

違い

より細かい操作ができるPlaywright

WebDriverはブラウザ非依存の規格のため、機能は汎用的になります。一方PlaywrightはChromeのプロトコルで通信するので、Chromeのプロトコルで実装されていることは全てできます。

例えばSelniumでBasic認証のサイトにアクセスする場合、毎回IDとパスワードをURLに埋め込む必要があります。

driver.get("https://[user_name]:[password]@example.com/sub_dir")

一方Playwrightの場合、Seleniumでのやり方も可能ですが、Chromeに認証のIDとパスワードを設定する機能があるので、それを使ってURLにIDとパスワードを埋め込まずにアクセスすることもできます。

const context = await browser.newContext({
    httpCredentials: {
        username: 'user_name',
        password: 'password',
    },
});
const page = await context.newPage();
await page.goto("https://example.com/sub_dir");

スマートフォンも操作できるSelenium

SeleniumはあくまでWebDriverと通信をしているに過ぎません。WebDriverの接続先をスマートフォンのブラウザにすることにより、Seleniumからスマートフォンのブラウザを操作することができます。

今回はWebクローリング用途の観点でしか試していませんが、実機を用いたテストなど、幅広く端末やブラウザを操作する必要がある場合にはSeleniumの方が向いています。

感想

Webクローリング

Playwrightの方がより細かい操作ができるのですが、WebDriverもかなり細かいことがき、ほとんどのWebクローリングにおいては、Selenium、Playwrightどちらを使っても大丈夫だと思います。

プログラムの書きやすさ

Playwrightの方が機能が豊富な分、よりプリミティブでプログラムが複雑・冗長になるように感じました。また、非同期関数を使うので、とっつきにくいかなと感じました。

一方Seleniumは同期関数で、WebDriverは汎用的な操作なので、Playwrightと比較してシンプルで書きやすいと感じました。

例えばPlaywrightでファイルダウンロードを書くと次のようになります。(Playwrightのドキュメントから抜粋)

const [ download ] = await Promise.all([
    page.waitForEvent('download'),
    page.locator('text=Download file').click(),
]);

const path = await download.path();

ダウンロードボタンをクリックしつつ、downloadイベントが発火するのを待ちます。イベント発火後は、ダウンロードパスが取得できるのを持ってして、ダウンロード完了となります。

このように、Playwrightは厳密にブラウザを直接操作している感が強く、かつ、同期・非同期を意識しながら書く必要があります。

Puppeteerとの比較

Playwrightは元Puppeteerの開発者が開発していて、関数はPuppeteerとほとんど同じで、使い方もほぼ同じです。今までPuppeteerを使っていたのでしたら、違和感なくすんなりと使えるようになると思います。

ドキュメント

Seleniumは大まかなことをやるのであれば、公式ドキュメントで事足ります。より深いことや、関数・引数の詳しい説明を知りたい場合は、APIドキュメントを参照することになるのですが、このAPIドキュメントの使い勝手があまりよくなく、ソースまで調べる必要があって不便でした。

一方Playwrightはきちんとドキュメントが整備されていて特に困ることはないかなと思います。

結論

Webクローリング用途であれば、正直SeleniumとPlaywrightどちらでも構わないと思います。ただ、ブラウザを直接触れるPlaywrightの方が、本当に困った時のクローリング能力は高いと思います。

Playwrightの方が機能豊富かつ非同期関数なので、学習コストは高めです。

Puppeteerを使っている人や、JavaScriptでプログラムを書いている人なら、Playwrightでもいいかなと思うのですが、初学者で手っ取り早くクローリングをしたいのであればSeleniumをお勧めします。

個人的には、今までPuppeteerを使っていたのでPlaywrightを使うことにしました。ただ、せっかく今回Seleniumにも触れたので、Selenium、Playwrightどちらも同程度に使えるよう、使い方メモを残しておければなと考えています。

前述したMicrosoft Power AutomateでのSeleniumの呼出は現在では非推奨になっていて、せっかくSeleniumの使い方を覚えたのですが、Microsoft Power Automateで役に立つことはなさそうで残念です。