🤖

【Playwright】ロボットに「私はロボットではありません」を押させる【reCAPTCHA】

2022/11/19に公開約2,500字

どうも、吉井駿一です。

この記事の意図

Playwright で CAPTCHA 認証を突破するという小ネタです。

※ 今回は筆者が作ったサイトで試していますが、実際に公開されている外部のサイトで試す場合は全て自己責任でお願いします。

実際の動き

こんな感じです。

CAPTCHA 認証とは

よく見る「私はロボットではありません」っていうやつです。
今回は Google が提供する reCAPTCHA を突破します。

こういうやつ。

ただ、画像選ぶパターン出たらアウトです。

reCAPTCHA の公式ドキュメント

https://developers.google.com/recaptcha/docs/v3

Playwright とは

microsoft が提供するスクレイピング用のライブラリです。
お手軽に使える上に TypeScript で動きます。
TypeScript でスクレイピングするなら正直これ一択だと思います。

Playwright の公式ドキュメント

https://playwright.dev/docs/intro

CAPTCHA 認証用のサンプルページ

Next.js でサラッと作りました。

https://re-captcha-bot.vercel.app/

GitHub

Playwright で「私はロボットではありません」を押すコード、公開してます。
https://github.com/yoshiishunichi/re-captcha-playwright

コードの解説

軽くコードを解説します。

まずは、 src/data/index.ts にスクレイピングする URL を定義しておきます。
本来は .env とかでやった方がいいですが、今回は雑にやります。

src/data/index.ts
export const pageUrl = "https://re-captcha-bot.vercel.app/";

そして、実際のスクレイピングのコードは以下です。

src/main.ts
import { chromium } from "playwright";
import { pageUrl } from "./data";

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();
  await page.goto(pageUrl, {
    waitUntil: "networkidle",
  });
  const reCaptchaContainer = page.locator("#re-captcha-container");
  const coordinate = await reCaptchaContainer.boundingBox();
  if (coordinate) {
    const { x, y } = coordinate;

    await page.waitForTimeout(2000);
    await page.mouse.move(x, y);
    await page.waitForTimeout(2000);
    await page.mouse.click(x, y);
    await page.waitForTimeout(2000);
  }
})();

Playwright のコード短くて良いですね〜
各箇所それぞれ説明すると、

  1. chromium.launch({ headless: false }) でブラウザを立ち上げてます。 headless: true だと画面非表示でバックグラウンドで実行されます。
  2. browser.newPage() で新しいページ開いてます。
  3. page.goto(pageUrl, {waitUntil: "networkidle"}) で対象のページに移動します。 pageUrl はさっき src/data/index.ts で用意したやつです。 waitUntil: "networkidle" で通信が終了するのを待機してます。
  4. page.locator("#re-captcha-container") でcaptcha認証用のボタンを取得しています。この #re-captcha-container はボタンの親要素の id です。これはページに応じて変えましょう。
  5. reCaptchaContainer.boundingBox() でボタン要素の座標を取得してます。これで押す位置を取得してます。
  6. page.mouse.movepage.mouse.click でさっき取得した位置にマウスを移動してクリックしてます。
  7. page.waitForTimeout みたいなのは自然な動きになるように待機しています。

以上です。簡単ですね。

最後に

いかがでしたか?
何か質問や感想あればコメントやTwitterで連絡ください。

あと、Twitterフォローしてくれたら嬉しいです。
普段はろくなツイートしてないですが…

吉井駿一のTwitter
https://twitter.com/ganja_tuber

では、また…

Discussion

ログインするとコメントできます