きっかけ
わたくしMyProtein社のプロテインを飲んでいます。
定期的にセールをやっているのですが、 種類毎に価格が違ったりします。
そこでスクレイピングで価格を抽出するツールを作りました。
法律的な話
MyProteinの利用規約に「スクレイピングを禁止する」文面は見当たりませんでした。
サーバーに負荷をかけないように注意すれば問題はなさそうです。
以下の記事を参考にさせて頂きました。
Webスクレイピングに関する10のよくある誤解 - Octoparse | スクレイピングツール
構想
スクレイピングといえばPythonですが、
あまり触った事がないため、JavaScript(Node.js)で作ってみます。
とりあえずテキストで表示できればよいので、CSVで出力することにします。
結果
こんな感じで取得できました。
アイスラテ,1kg,¥3,890 アイスラテ,2.5kg,¥7,390 アイスラテ,5kg,¥14,290 アイスラテ,250g,¥1,590 アイリッシュ コーヒー,1kg,¥3,890 アップルクランブルとカスタード,1kg,¥3,890 アップルクランブルとカスタード,2.5kg,¥7,390 イートン メス,1kg,¥3,290 …省略
開発
使ったライブラリはpuppeteer(パペティア)
コマンドでChromeを制御するためのライブラリです。
(デフォルトはヘッドレスなので画面が表示されることもありません)
GitHub - puppeteer/puppeteer: Headless Chrome Node.js API
ブラウザを起動してホエイプロテインの販売ページにアクセスするソースコード
const puppeteer = require("puppeteer"); (async () => { const browser = await puppeteer.launch({ }); const page = await browser.newPage(); await page.goto( "https://www.myprotein.jp/sports-nutrition/impact-whey-protein/10530943.html" ); /* ここでゴニョゴニョして価格を抽出する */ await browser.close(); })();
ブラウザ操作する例はこんな感じ
# セレクタを指定してクリック
await page.click("#mainContent");
またサーバーに負荷をかけないように、ボタンクリックやドロップダウンの選択は1秒待つようにしました。
await page.waitForTimeout(1000);
APIはdocsにまとめられています。
https://github.com/puppeteer/puppeteer/blob/main/docs/api.md
要素を取得するには、様々な方法があるようですが違いがよくわかっていません…
- page.evaluete()
- page.$()
- page.$$()
- page.$$eval()
- page.$eval()
自分はevaluete()
しか使いませんでした。
イメージでは「ブラウザ内で実行する処理」を関数で渡す感じ。
documentオブジェクトが使えたので、ブラウザ内のJavaScriptを書くイメージで使えました。
作ったツールはこちら
目的は達成しました。puppeteerもおもしろかったです。
ちゃんと理解してないので、もう少しやってみたい気持ちになりました。