(【追記】記事公開後、内容を見直して高速化に成功しました。)
ブログの内容が溜まってくると、完全ランダムで過去記事を表示したいなーって思うときがありますよね。
「はてなブログ ランダム」とかで検索してみると、あらかじめ表示する記事のリストを用意しておいて、その中からランダムで表示させるって仕組みは見つかるんですけど、過去のすべての記事から無作為に表示するプログラムは無いっぽい。
いちいちリストを更新するのもめんどくさいし、どうせなら全部の記事から選ばせたいじゃないですか。
というわけで、すべての過去記事からランダムで記事を表示するボタンを作ってみました。
えーっと、あらかじめ言っておきますが、めちゃくちゃ無理やりです。そしてクッソ遅いです。記事公開直後は、ボタンを押してから画面が切り替わるまで5秒以上かかるというクソ仕様だったのですけど、その後の改善によりクリックしたら即ランダム記事へ飛ぶようにしました。多少はましになったかな……。
ってことをご了承いただいた上で、下のボタンを押してみてください。
はてなブログで運用している映画ブログ「MoyaCinema」の記事にランダムに飛びます。
あ、「読み込み中…」となってる場合はまだボタンの起動準備ができておりません。
読み込み完了次第、それっぽい表示に切り替わるので、数秒お待ちくださいませ。
(PC版・スマホ版の Chrome では動作確認しております。古いブラウザでは動かない場合があります。)
Contents
仕組み
指定されたブログの全記事のURLをさっくり取ってこれる仕組みがあれば簡単な話だったんですが、残念ながら一度に7件しか取ってこれないとか、そもそもOAuth認証が必要だとかで、思ったようなAPIが公開されてなかったんですよね。
参考: はてなブログドキュメント一覧 – Hatena Developer Center
で、かわりにこのランダムボタンが何をやってるかというと、ブログのトップから「次のページ」ボタンを経由して記事一覧をさかのぼり、ページ中の記事URLを全部引っこ抜いて、最後にどれかひとつに飛ぶという、ひっっっっじょうに頭のわるい動作をしております。ひでえ……。
つまり、ブログの記事が多いほど読み込みに時間がかかるし、一覧表示の件数が少ないとこれまた時間がかかります。当ブログ「NZ MoyaSystem」は記事件数300そこそこですが、それでも読み込み完了まで約5秒。600以上記事のある某ブログさんでは25秒かかりまして、パフォーマンス的にはさっぱりお話にならないレベルです。
まぁ、モダン JavaScript での HTTP リクエスト&レスポンス取得、テキストからDOMへのパース、非同期処理なんかは週末プログラミングとして書いてて勉強になりました。もっと皆さんのお役に立てる結果になればよかったんですが、そこは今後はてなさんがブログAPIを充実させてくれることに期待しましょう(責任転嫁)!!!
ソースコード
最後にソースコードを紹介しておきます! 自分のブログに導入したいという方は参考にしてみてください(まったくオススメはしませんが)。あと、このスクリプトをブログ記事本文に埋め込むとなぜか Bad Request が帰ってきて保存できません。デザイン設定からタイトル下に埋め込むか、外部ファイルに切り出して読み込むとうまくいきます。
JavaScript
var parser = new DOMParser(); async function getHtmlFromUrl(url) { var page = await fetch(url).then(r=>r.text()); return parser.parseFromString(page, 'text/html'); } function getEntryLinks(html) { var links = Array.from(html.querySelectorAll('.entry-title-link')); return links ? links.map(e=>e.href) : []; } function getNextLink(html) { var next = html.querySelector('.pager-next a'); return next ? next.href : ''; } async function getAllEnrtyLinks(url, entries) { entries = entries || []; var html = await getHtmlFromUrl(url), links = getEntryLinks(html), next = getNextLink(html); entries = entries.concat(links); if (next) { return await getAllEnrtyLinks(next, entries); } else { return entries; } } var entries; getAllEnrtyLinks('https://www.hassy-blog.com/').then(function(result){ entries = result; var button = document.querySelector('.random_btn'); button.disabled = false; button.innerHTML = 'ランダム記事へジャンプ!' })
ランダムボタン
<button class="random_btn" onclick="location.href=entries[Math.floor(Math.random() * entries.length)]" disabled>読み込み中...</button>
<style> .random_btn{ display: inline-block; padding: 0.5em 1em; text-decoration: none; border-radius: 4px; color: #ffffff; background-image: -webkit-linear-gradient(#6795fd 0%, #67ceff 100%); background-image: linear-gradient(#6795fd 0%, #67ceff 100%); box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.29); border-bottom: solid 3px #5e7fca; font-size:1.2em; } .random_btn:disabled{ background-image: -webkit-linear-gradient(#555555 0%, #f4f4f4 100%); background-image: linear-gradient(#555555 0%, #f4f4f4 100%); } </style>
ボタンのデザインは「CSSで作る!押したくなるボタンデザイン100(Web用)」から借用させていただきました。
GitHub はこちら。
github.com