Bloggerの関連記事表示を強化する
この記事は、既に最新ではありません。最新の関連記事は、「Blogger用の関連記事表示機能:FeedRelatedPosts.js」を使用しています。
「Bloggerに関連記事を表示する」の続きです。
「A Simple Related Posts Widget For Blogger」の問題点
- 関連度が低い
- 完全なランダムの連続から偏ったランダムに修正する
- 複数のラベルで重複している記事の表示確率を上げる
- 重複記事は関連度が高いものと仮定する
- コメントの記載のある記事の表示確率を上げる
- コメントのある記事は、人気があるものと仮定する
- 複数のラベルで重複している記事の表示確率を上げる
- 関連度が良くなったわけではない (´・ω・`)
- 完全なランダムの連続から偏ったランダムに修正する
- 同期読込みのため、ページの読込みをブロックする
- 非同期(async)で読込むように修正する
- 非同期の読込みで、最後のRSSフィードを読込んだ段階で関連記事を出力する
- 表示速度向上
- RSSフィードの記事内容をすべて読込むため、通信量が増える
- 概要のみ読込むように修正する
/feeds/posts/default/
→/feeds/posts/summary/
- 最新の10件のみ読み込む仕様はそのままとする
- 概要のみ読込むように修正する
- 関連記事が1つだとヘッダ部分が表示されない
- 関連記事が1つでもヘッダ部分を表示するように修正する
補足
A Simple Related Posts Widget For Bloggerでは、画像を表示できませんでした。ですが、Customizable Related Posts Widget for Bloggerであれば、画像を表示できるようです。
筆者は、画像表示の必要がなかったため、下記のコードでは非対応です。ですが、RSSフィード上に画像のurlが出力されていることまでは確認しました。画像urlの収集箇所はコメントアウトしてあるため、好みに合わせて修正ください。
修正結果
修正と言いながら、概念は同じでも全取っ替えです。
結果
※FontAwesome部分のみ下記コードと異なります。
style
#related-posts { margin: 0.5em 0; border: 1px solid #aaa; display: none; } #related-posts h4 { font-size: 1.25em; font-weight: normal; color: #fff; background-color: #888; margin: 0; border: none; } #related-posts ul { padding: 0; list-style-type: none; background: #f9f9f9; margin: 0; } #related-posts li { padding: 0; } #related-posts li a { display: block; text-decoration: none; padding: 3px 1em 3px 2.5em; border-bottom: 1px solid #ddd; } #related-posts li a:hover { background: #eee; } #related-posts li:last-child a{ border-bottom: none; }
※BloggerテンプレートなどのCSSに依存します。配置環境毎に修正が必要です。
js
(function(root, factory) { if (!root.RelatedPosts) { root.RelatedPosts = factory(); } })(this, function() { "use strict"; let _this = function RelatedPosts_constructor() {}; let count = 0; // フィード読み込み完了数 let limit = 0; // フィード読み込み予定数 let urls = []; // URL一覧 let titles = []; // タイトル一覧 let current = ''; // 標的ページ let title = 'RelatedPosts'; // 関連記事タイトル let maxresults = 5; // 最大関連記事数 // 初期化 _this.init = function RelatedPosts_init(currenturl, head, max) { current = currenturl; title = head; maxresults = max; }; // フィード数分をカウントする _this.counter = function RelatedPosts_counter() { limit++; }; // 関連記事を書き込む function RelatedPosts_write() { // ランダムインデックス生成 let indexs = Array(urls.length); for (let i=0, r; i<indexs.length; i++) { r = Math.floor(Math.random() * (i+1)); if (r !== i) indexs[i] = indexs[r]; indexs[r] = i; } // 関連一覧の作成(重複要素は、出現しやすい) let dups = []; let items = []; for (let i=0; i<indexs.length && dups.length<maxresults; i++) { if (dups.indexOf(urls[indexs[i]]) == -1) { dups.push(urls[indexs[i]]); items.push('<li><a href="' + urls[indexs[i]] + '">' + titles[indexs[i]] + '</a></li>'); } } if (items.length > 0) { let line = []; line.push('<h4>' + title + '</h4>') line.push('<ul>'); for (let i=0; i<items.length; i++) { line.push(items[i]); } line.push('</ul>'); let posts = document.getElementById('related-posts'); posts.insertAdjacentHTML('beforeend', line.join('')); posts.style.display = 'block'; } } // フィードの要素を追加する _this.add = function RelatedPosts_add(json) { let m = current.match(/^https?:\/\/(.+$)/); let http = ''; let https = ''; if (m != null) { http = 'http://'+m[1]; https = 'https://'+m[1]; } for (let i=0; i<json.feed.entry.length; i++) { let entry = json.feed.entry[i]; for (let k=0; k<entry.link.length; k++) { if (entry.link[k].rel == 'alternate') { if (!(http == entry.link[k].href || https == entry.link[k].href)) { if (0 != entry.thr$total.$t) { // コメントありの時 // 出現確率を上げる titles.push(entry.title.$t); urls.push(entry.link[k].href); } titles.push(entry.title.$t); urls.push(entry.link[k].href); // サムネイル画像 // Bloggerに画像が保存していることが必須 // Googleフォト等で別に画像をロードしている場合、存在しない //if (entry.media$thumbnail) { imgs.push(entry.media$thumbnail.url); } //else { imgs.push(''); } } break } } } count++; if (count == limit) { RelatedPosts_write(); urls.splice(0, urls.length); titles.splice(0, titles.length); } }; return _this; });
template
<b:if cond='data:blog.pageType == "item"'> <style type='text/css'> ... 上記のstyle </style> <script type='text/javascript'> //<![CDATA[ ... 上記のjs //]]> </script> <div id='related-posts'> <script type='text/javascript'>RelatedPosts.init("<data:post.url/>", "関連記事", 5);</script> <b:loop values='data:post.labels' var='label'> <script type='text/javascript'>RelatedPosts.counter();</script> </b:loop> <b:loop values='data:post.labels' var='label'> <script async='async' expr:src='"/feeds/posts/summary/-/" + data:label.name + "?alt=json-in-script&callback=RelatedPosts.add&max-results=10"' type='text/javascript'/> </b:loop> </div> </b:if>
※</article>
の直前などに配置する。
※RelatedPosts.init
の引数でURL、タイトル、関連記事数を指定する。