最近Typescript/Playwright を利用しているので、 Playwrightを利用すると簡単にクローラが作れそう。
というところから技術調査をしたところcrawleeが見つかったので試しに利用してクローラをつくってみた話。
以下に手順を記す。
プロジェクトの作成
https://crawlee.dev/docs/introduction/setting-up
setupを参考に
npx crawlee create my-crawler
を実行する。
crawleeがインストールされていないと
Need to install the following packages: crawlee@3.3.1 Ok to proceed? (y)
のようにcrawleeをインストールするか聞いてくるので y
でインストールする。
その後
? Please select the template for your new Crawlee project Getting started example [TypeScript] Getting started example [JavaScript] CheerioCrawler template project [TypeScript] ❯ PlaywrightCrawler template project [TypeScript] PuppeteerCrawler template project [TypeScript] CheerioCrawler template project [JavaScript] PlaywrightCrawler template project [JavaScript]
のように、どのテンプレートを利用するか聞いてくるので、上下キーで PlaywrightCrawler template project [TypeScript]
を選択する。
これで、 my-crawler ディレクトリにテンプレートが作成される。
クローラの作成
クローラ本体は、 src/routes.ts に登録していく。
ファイルを見ると addDefaultHandler
と addHandler 'detail'
がすでに登録されている。
defaultHandler
DefaultHandlerの中身が、クローラの開始時に呼ばれる。
router.addDefaultHandler(async ({ enqueueLinks, log }) => { log.info(`enqueueing new URLs`); await enqueueLinks({ globs: ['https://crawlee.dev/**'], label: 'detail', }); });
globs, label の組みで、 実行するクローラを変えられる。 globにマッチしたURLはこのlabelでキューイングされ、クローリング対象となる。
enqueueLinksすると、現在のページの linkを全部見てくれるので、自分でリンクを探してキューイングしなくてよいのがとても楽。
ただし、動的ページで、後でlinkが生えてくるような場合は、 playwrightを利用して、linkが生えてくるのを待ってからenqueuLinksする必要がある。
たとえば
await page.locator("#page-1").waitFor({ state: "attached" });
などで 読み込みをまったりしている。
別のクローラを利用したければ、 enqueueLinksを複数書いて、それぞれURLパターンを登録していく。
handler for label
router.addHandler('detail', async ({ request, page, log }) => { const title = await page.title(); log.info(`${title}`, { url: request.loadedUrl }); await Dataset.pushData({ url: request.loadedUrl, title, }); });
こちらが、 enqueueLinksで label: 'detail' としてキューイングしたURLが渡ってくるクローラ本体。
この中で好きにスクレイピングするコードを書くと良い。
もちろん、この中でも enqueueLinksでキューイングできる。 何度もキューイングしても、同一URLは2度はクローリングしないように制御されているので安心。
好きなlabelでenqueueLinksして、 addHandlerでlabelを指定してあげれば、いくらでもnestしたり、URLタイプごとに処理を分けたりできる。
開始URLの設定
src/main.ts に startsUrlsという配列が定義されているので、 そこにクローリング対象のトップURLを並べればよい。 コマンドライン引数からURLを組み立てるなどすると、汎用性が上がる。
実行
npm run start:dev
で実行できる。コンパイルしたものを利用したい場合は
npm run build
でビルドしておき、
npm run start:prod
でビルドしたものを実行できる。
終わりに
playwrightを利用すればseleniumのようにweb driverとbrowserのバージョン不一致問題など、面倒ごとなくクローラが作成できると思っていたら、crawleeというとても便利なライブラリが見つかり、
とても簡単にクローラが書けることがわかった。
わずか20行ほどコードを書くだけでクローリングできて、とても楽だった。
今後はメモリに余裕のある環境では積極的にcrawleeを使っていきたい。