スクレイピングのためのgRPCのレスポンスデータを処理するアプローチ【CanvasKitと闘う】
Node.js環境でPlaywrightを使って CanvasKit + gRPC で作られたWebサイトをスクレイピングしています。
CanvasKitはHTMLタグによるスクレイピングができません。
かなり難しいスクレイピングの部類です。
これのスクレイピングの手法は下記記事にしてあるのでご覧ください。
今回は .route()
で盗み見みした gRPC形式のレスポンスデータを正規表現でデータ抽出するアプローチをご紹介します。
gRPCのレスポンスデータは複雑
gRPCのデータはJSONと異なりシリアライズという処理が施されています。
.proto
というファイルがあれば読みやすい形式に変換できるようなのですが、そんなものは当然提供される訳が無いので別の解決方法を探らなければなりません。
1. 制御文字を16進数に変換しよう!
制御文字とは先程のキャプチャの赤文字の箇所になります。
これは文字列として扱えないのでコピペもできません。AIに聞こうにも聞けません。
ということで、AIさんに聞けるようにするためにも制御文字を16進数に変換しておきましょう。
const convertControlCharsToHex = input.replace(/[\x00-\x1F\x7F]/g, (char) => {
// 改行文字 (\n) は特別に処理
if (char === "\n") {
return "\\n";
}
// その他の制御文字を16進数に変換
const result = `<${char.charCodeAt(0).toString(16).padStart(2, "0")}>`;
return result;
});
こんなコードで変換できます。(AIさんに聞いたものなので詳しくは理解していませんが問題なく動きました。)
16進数に変換するだけで <00><01>
などの特徴的な文字列が上記のように出現します。
かなり正規表現での処理がしやすい状態になります!
2. まとまりのあるデータに分轄できそうな特徴的な文字列を探そう
商品一覧のデータであれば、商品ごとにデータのまとまりがあるはずです。商品IDや商品タイトル、価格など、それらがひとまとまりに保たれつつも、商品グループごとに分けられそうな特徴的な文字列を探してみましょう。
分轄は単純に .split()
で分けるだけでOKです。
3. 分轄したデータグループごとに正規表現で処理をしていこう!
ここまで来ればあとは正規表現による処理だけです。
for文で商品グループごとに処理をしていきましょう。
正規表現は下記のように分けておくとメンテナンスがしやすいでしょう。
また、分轄された正規表現の方がAIの回答の精度が高い印象です。
const idRegex = /<12><08>(\d+)/;
const titleRegex = /<1a>(.+?)"/;
const priceRegex = /�<03>(<03>|<02>|<04>)(\d+)�<04>(<03>|<02>|<04>)(\d+)/;
const imageRegex = /(https:\/\/hoge\.imgix\.net\/[^sales_badges].+?\.(jpg|jpeg|png|webp|avif|JPG|PNG|WEBP|AVIF|JPEG))/;
// 正規表現を実行する
const idMatch = idRegex.exec(splitText[key]);
const titleMatch = titleRegex.exec(splitText[key]);
const priceMatch = priceRegex.exec(splitText[key]);
const imageMatch = imageRegex.exec(splitText[key]);
正規表現自体に問題が無いかを確認するには if (!priceMatch) { console.log(splitText[key]); }
のようにして文字列を確認しましょう。改善できそうかどうかチェックして正規表現を修正していきましょう。
最後に if (idMatch && titleMatch && priceMatch && imageMatch)
のように全ての正規表現が通ったものを正データとして取り扱い、DBに保存するなどすればOKです。
おわりに
これで CanvasKit + gRPCで作られたスクレイピングが困難なサイトでもデータ収集が可能となりました。やったぜ。
スクレイピングはマジで正規表現ゲーですね。
Claude AIさん最高!
Discussion