5
1

ProtoPediaの作品データを簡易的に取得して指標分析など

Posted at

ヒーローズリーグ2023お疲れ様でした!

ヒーローズリーグは老舗のものづくり開発コンテストって感じで2023年の決勝が先日終わりました。

ヒーローズリーグとは?はこちらの記事を読んでみましょう。

僕も出しましたけど賞に引っかからず...

288作品の情報を一覧化してみる

個人的な興味(理由はあるけど深くは言わない)で作品の情報を抜き出しつつソートしたりしたいなと思いました。

今回の応募作品は288作品でした。

この情報を手で取るのは大変で、ProtoPediaのAPIはあるけどなんか 挙動が怪しかったのでAPIは使わずにサイトから抜き出してみるチャレンジをしてみます。

サイトの構成

こんな感じで作品がdivタグ要素のBOXに入っています。 "proto-box"というclassが付いていたので分かりやすかったです。

スクリーンショット 2023-12-05 10.46.17.png

デフォだと30件しか表示されず、もっと見るボタンが必要

30件しか表示されないのでサーバー側で生成された初期状態だと30件のレンダリングになってる模様でした。

スクリーンショット 2023-12-04 19.08.23.png

もっとみるボタンがページ下部にあり、これを押すと追加で30件がロードされる仕様っぽいです。

スクリーンショット 2023-12-05 10.47.59.png

Fetch()などのHTTP Requestで抜き出すことはできず、ボタンエミュレートなどが必要になりますね。

Puppeteerさんを使ってボタンぽちぽち押させる

もっと見るボタン再帰関数

もっと見るボタンはnextBtnというidが振ってあったので特定は楽でした。

<button id="nextBtn" type="button" class="btn-reset btn primary">もっと見る</button>
  1. clickMore関数を作りつつボタンを押す、これを再帰的に呼び出します。
  2. 要素が最後までいくともっと見るボタンが表示されなくなる
  3. もっと見るボタンを押そうとするけどボタンが無くてエラーがでて異常終了

こんな流れにして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件って何かおかしい。。

スクリーンショット 2023-12-05 1.42.42.png

おそらく賞を取ったときの表示が追加されたりしてるのかクリックしたときに何かDOM生成が過剰にされるようなバグが発生しているのか... といった感じかなと予想します。

こちらの記事を参考にさせていただき、Mapを使ってユニークにしました。

const uniqueProtoItems = Array.from(
    new Map(protoItems.map((item) => [item.title, item])).values()
);

スクリーンショット 2023-12-05 1.47.11.png

予想はあたりでタイトルでユニークにしてみたら288件になりました。

要素を取ってみる

情報として取れそうなのは

  • 作品タイトル
  • URL
  • ビュー数
  • いいね数
  • コメント数
  • サムネイル画像URL

スクリーンショット 2023-12-05 11.02.29.png

各要素はこんな感じでとれます。

<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位があるのが良いところなので、順位つけるのよくない気もしますが、
ただ個人的な興味というところでページ上で見えてるデータから算出はできるのでかるく出してみました。

順位 ビュー数 Like数 Comment数
1位 Type-C 危機一発 (18884 view) TechSeebo (49 Like) 架空の奥さんが料理して待ってくれる装置 (14 comment)
2位 サービス終了になった LINE CLOVA 達に第二の人生を歩ませる (8825 view) Cheifoon (49 Like) やる気急上昇!航空電子機器風MTGヘルパー 「とぐるちゃん」 (13 comment)
3位 ショップバリュー ~長さを売る自販機~ (4199 view) Type-C 危機一発 (47 Like) 柿 : ピー (かきたいぴー) (10 comment)

こうみると、案外被りがないというのがすごいですね。

ビュー数、いいね数、コメント数でそれぞれ盛り上がり方が違うんだろうなと思ったりします。

それぞれ面白い作品ばかりなので↑のURLからページを見てみてください!

( もう少し多めのデータはこちらにメモ的においてます。 )

蛇足

このテーブル作るのだるいなって感じだったんですけど、ChatGPTさんありがたいです。

スクリーンショット 2023-12-05 12.38.07.png

まとめ

APIを使わずにProtoPediaの作品情報を簡易的に取ってみました。

APIが重かったのですが一旦これで取れそうな雰囲気でてきたのでDOM構造あまり変えないで欲しいなと思ってたりします。

おしまい。

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1