8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Qiita】新着記事一覧ページを疑似再現する

Last updated at Posted at 2022-12-26

Qiitaの新着記事一覧殺されました

そのため現在は、全ユーザーに一律の情報を見せるのではなく、ユーザー1人1人の興味に合わせて自分が欲しい情報に出会えるように、ホームフィードや、タイムラインフィードを用意しております。

そんな余計なことしなくていいから全記事を一覧させろ。

と嘆いていても死んだ子は帰ってこないので、ここでは逆転の発想で考えましょう。
すなわち、ありとあらゆるタグを全てフォローすることで、タイムラインに新着記事一覧ページを疑似再現するのです。

Qiita APIにtags/:tag_id/followingがあるので、これをひたすら延々叩くことにしましょう。

……ところで:tag_idってなんだ?
タグ一覧ページにもタグ詳細にもそれっぽい値が見当たらないんだが。
と調べてみたらIDとかではなくタグの文字をそのまま入れればいみたいでした。
つまりはtags/php/followingにPUTすればタグPHPをフォローできるということです。

そんなわけでさくっと作成。

(new ITEMS())->run();

class ITEMS{

    public function run(){
        // とりあえず100ページ
        $i = 0;
        while($i++<100){
            // タグ一覧を取得
            $tags = $this->getTags($i);

            foreach($tags as $tag){
                // タグをフォローする
                $this->followTag($tag);
            }
        }
    }

    /**
     * タグ一覧を取得
     * @param int ページ
     * @return array タグリスト
     */
    private function getTags(int $page):array{
        // 取得
        $url = 'https://qiita.com/tags?page='.$page;
        $f = file_get_contents($url);

        // タグを取り出す
        preg_match_all('|TagList__label" href="/tags/(.*?)">|', $f, $matches);
        return $matches[1];
    }

    /**
     * タグをフォローする
     * @param string タグ
     */
    private function followTag(string $tag):void{
        static $count = 0;
        $count++;

        $url = sprintf('https://qiita.com/api/v2/tags/%s/following', $tag);

        $curl = curl_init($url);
        $option = [
            CURLOPT_CUSTOMREQUEST => 'PUT',
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                'Authorization: Bearer XXXXXXXX',
                'Content-Type: application/json',
            ],
        ];
        curl_setopt_array($curl, $option);
        $result = curl_exec($curl);

        // 失敗したら死
        if($e = curl_error($curl)){
            var_dump($e, curl_getinfo($curl));
            die;
        }

        echo sprintf("COUNT: %d  TAG: %s follow. \n", $count, urldecode($tag));
        sleep(1);
    }
}

タグ一覧ページを100ページ目まで拾ってきて、取得したタグを全てフォローするという力業になっています。

いろいろ失敗

なんか途中から急にAPIの呼び出しが早くなったんですよ。
Webで見るとフォローが972で止まっていました。

01.png

なんで?と思ったら、APIの返り値が403 Forbiddenになっていました。
そして403 Forbiddencurl_error()に反応しなかったのでループが止まらなかったというわけです。

よく考えたらsleep(1)ではAPIの呼び出し制限1時間に1000回に思いっきり引っかかってましたね。

ということでsleep(5)にして、さらにエラーが引っかかるように↓を追加して実行を続行。

if(curl_getinfo($curl)['http_code']>300){
    var_dump(curl_getinfo($curl), $result);
    die;
}

今度はa&b&の入ったタグの登録で引っかかりました。
おそらくクエリパラメータと間違えられて、そこでURLのパースが途切れたと思われます。
&amp;にしても駄目でした。
解決策はあるんだろうけど、面倒なので&が入っていたらパスすることにして続行。

02.png

はい、無事に10000タグのフォローに成功しました。

あ、最後の3タグは手動です。

タグ10000番目が15記事とかです。
従って、これ以下のマイナーなタグしか指定されていないとか、そもそもタグを設定してない記事は引っかからないのですが、そのような記事以外は全て新着順に表示されるようになったはずです。
10000なのは単にきりがよかったからというだけなので、もっと伸ばして10万タグをフォローしたりすれば漏れもほとんどなくなるでしょう。

実行後のタイムライン

03.png

※実際は30件表示された下に『もっと読む』ボタンです。

どうしてここページングじゃないんですか?

ページングにするか、ページングしないんならせめて自動読み込みにするかのどちらかにしてくれ。
自動じゃない追加読み込みは、非常に苦痛なのでやめてほしいところ。

とまあ大きな不満こそありますが、ひとまず新着記事一覧をほぼ再現することに成功しました。
めでたし。

ところで1万タグを含む記事の検索ってどうやってるんだろうか。

おまけ

検索画面でcreatedだけ設定して新着順検索すると新着記事一覧になります。

一日一万件感謝のフォロー、意味なし!

04.png

検索画面とタイムラインの表示内容が、ほぼ同じになっていますね。
考え方自体は間違っていなかったということでよいでしょう。
問題は、わざわざこんなことしなくてもほぼ同じ機能が既に存在していたということだけですな。

ちなみに実は1記事だけ異なるのですが、これは検索画面は作成日時、タイムラインの場合は更新日時の順になっているからのようです。

8
2
3

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
8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?