ヒーローズリーグ2023お疲れ様でした!
ヒーローズリーグは老舗のものづくり開発コンテストって感じで2023年の決勝が先日終わりました。
ヒーローズリーグとは?はこちらの記事を読んでみましょう。
僕も出しましたけど賞に引っかからず...
288作品の情報を一覧化してみる
個人的な興味(理由はあるけど深くは言わない)で作品の情報を抜き出しつつソートしたりしたいなと思いました。
今回の応募作品は288作品でした。
この情報を手で取るのは大変で、ProtoPediaのAPIはあるけどなんか 挙動が怪しかったのでAPIは使わずにサイトから抜き出してみるチャレンジをしてみます。
サイトの構成
こんな感じで作品がdivタグ要素のBOXに入っています。 "proto-box"というclassが付いていたので分かりやすかったです。
デフォだと30件しか表示されず、もっと見るボタンが必要
30件しか表示されないのでサーバー側で生成された初期状態だと30件のレンダリングになってる模様でした。
もっとみるボタンがページ下部にあり、これを押すと追加で30件がロードされる仕様っぽいです。
Fetch()などのHTTP Requestで抜き出すことはできず、ボタンエミュレートなどが必要になりますね。
Puppeteerさんを使ってボタンぽちぽち押させる
もっと見るボタン再帰関数
もっと見るボタンはnextBtn
というidが振ってあったので特定は楽でした。
<button id="nextBtn" type="button" class="btn-reset btn primary">もっと見る</button>
- clickMore関数を作りつつボタンを押す、これを再帰的に呼び出します。
- 要素が最後までいくともっと見るボタンが表示されなくなる
- もっと見るボタンを押そうとするけどボタンが無くてエラーがでて異常終了
こんな流れにして288件を表示させました。
件数指定にするかなど悩みましたが一旦ここに行きつきました。
//もっとみるをクリック
async function clickMore(page, selector){
try {
console.log(`...`);
await page.click(selector.moreButton); // もっとみるボタン s#nextBtnをクリック
await setTimeout(1000 * 1); // 待つ
return clickMore(page, selector); //再帰実行
} catch (error) {
//エラーが出たら終了
console.log(`もっとみる終わり`);
}
}
528件とれてた
試してたら、proto-boxの要素が528件取れてました。
ヒーローズリーグ2023の応募件数は288件でしたね。528件って何かおかしい。。
おそらく賞を取ったときの表示が追加されたりしてるのかクリックしたときに何かDOM生成が過剰にされるようなバグが発生しているのか... といった感じかなと予想します。
こちらの記事を参考にさせていただき、Mapを使ってユニークにしました。
const uniqueProtoItems = Array.from(
new Map(protoItems.map((item) => [item.title, item])).values()
);
予想はあたりでタイトルでユニークにしてみたら288件になりました。
要素を取ってみる
情報として取れそうなのは
- 作品タイトル
- URL
- ビュー数
- いいね数
- コメント数
- サムネイル画像URL
各要素はこんな感じでとれます。
<span>
要素の1個目が閲覧数、2個目がいいね数、3個目がコメント数になってますね。
const protoItems = await page.evaluate((selector) => {
let protoItems = [];
document.querySelectorAll(selector).forEach(item => {
const protoItem = {
url: item.href,
title: item.querySelector("H2").textContent,
view: item.querySelectorAll(".count1 span")[1].textContent,
like: item.querySelectorAll(".count2 span")[1].textContent,
comment: item.querySelectorAll(".count3 span")[1].textContent
}
protoItems.push(protoItem);
});
return protoItems;
},selector.protoBox);
上だけ数字で一覧化
ヒーローズリーグは趣旨的にあえてランキングは出してないと思います。
みんなの1位があるのが良いところなので、順位つけるのよくない気もしますが、
ただ個人的な興味というところでページ上で見えてるデータから算出はできるのでかるく出してみました。
こうみると、案外被りがないというのがすごいですね。
ビュー数、いいね数、コメント数でそれぞれ盛り上がり方が違うんだろうなと思ったりします。
それぞれ面白い作品ばかりなので↑のURLからページを見てみてください!
( もう少し多めのデータはこちらにメモ的においてます。 )
蛇足
このテーブル作るのだるいなって感じだったんですけど、ChatGPTさんありがたいです。
まとめ
APIを使わずにProtoPediaの作品情報を簡易的に取ってみました。
APIが重かったのですが一旦これで取れそうな雰囲気でてきたのでDOM構造あまり変えないで欲しいなと思ってたりします。
おしまい。