Blogger情報リーダー

2021/01/19
2
サムネ画像

Bloggerブログ限定の情報リーダーを作ってみました。気になるあのブログの最新情報をチェック!

※○○.comはwww.○○.comと入力してください。

ツールに関して

フィードの勉強もかねてちょっとしたツールを作ってみました。これはJavaScriptを使用したツールで、JSON形式のフィードから情報を取得して表示します。

情報を見たいブログのURLを入力してCheckを押すと、ブログの最終更新日時、運営者、総投稿数などを一覧で確認することができます。

※Blogger固有のフィード形式にのみ対応しているため、Blogger以外のブログの情報を見ることはできません。

コードに関して

需要があるかは謎ですが、こちらのコードを投稿や固定ページ等にコピペするとBlogger情報リーダーをお使いのブログやサイトに設置することが可能です。

<form name="blog-url">
  <input id="b-url" type="text" placeholder="example.blogspot.com">
  <input onclick="start()" type="button" value="Check">
  <input onclick="clr()" type="button" value="Clear">
</form>
<div id="blog-info"></div>
<script type='text/javascript'>
  var flag = null;
  var timer = null;
  var catnum = 5; // 表示カテゴリー数
  var rpnum = 10; // 表示投稿数  
  
  function start() {
    flag = 0;
    var url = document.getElementById("b-url").value;
    if (url == '') {
      alert('URLを入力してください');
      return;
    }
    var feedurl = '//' + url + '/feeds/posts/default?alt=json-in-script&callback=getdata';
    var scr = document.createElement('script');
    scr.setAttribute('type', 'text/javascript');
    scr.setAttribute('src', feedurl);
    document.getElementById("blog-info").after(scr);
    scr.remove();
    timer = setInterval(confirm, 1500);
  }
  
  function clr() {
    document.getElementById("b-url").value = '';
    document.getElementById("blog-info").innerHTML = '';
  }
  
  function getdata(json) {
    var blogtitle = json.feed.title.$t;
    var update = new Date(json.feed.updated.$t);    
    var author = json.feed.author[0].name.$t;
    var profurl = json.feed.author[0].uri.$t;
    var posttotal = json.feed.openSearch$totalResults.$t;
    var entry, postdate, posttitle, posturl, postimg, blogurl;
    var Category = new Array();
    var postDate = new Array();
    var postTitle = new Array();
    var postUrl = new Array();
    var postImg = new Array();
    
    flag = 1;
    if (json.feed.category) {
      for (var i = 0; i < json.feed.category.length; i++) {
        Category.push(json.feed.category[i].term);
      }
    }
    for (var i = 0; i < json.feed.link.length; i++) {
      if (json.feed.link[i].rel == 'alternate') {
        blogurl = json.feed.link[i].href;
        break;
      }
    }
    blogurl = blogurl.slice(8, -1);
    for (var i = 0; i < json.feed.entry.length; i++) {
      entry = json.feed.entry[i];
      postdate = entry.published.$t;
      posttitle = entry.title.$t;
      for (var k = 0; k < entry.link.length; k++) {
        if (entry.link[k].rel == 'alternate') {
          posturl = entry.link[k].href;
          break;
        }
      }
      if ("media$thumbnail" in entry) {
        postimg = entry.media$thumbnail.url;
        if (postimg.match(/s72-c/)) {
          postimg = postimg.replace('s72-c', 's100-c');
        }
      } else {
        // No Image
        postimg = "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpJms9mnNPfhuWkuWFCoMCTzb9wop7cvTs5LlisKd79TN06TOEHDwmB5mMkes27EY6H9XQpbkqNOCMDA3WoyWJDi8D2C3-SDQCYI3UJzKTE5QG1fdGjSBNC5snDeJmc-x9EggqNenPEmU/s100/";
      }
      postDate.push(postdate);
      postTitle.push(posttitle);
      postUrl.push(posturl);
      postImg.push(postimg);
    }
    
    var infoHTML = '';
    var pdate = new Date(postDate[0]);
    infoHTML += '<div class="info-wrapper">';
    infoHTML += '<div class="blog-title">' + blogtitle + '</div>';
    infoHTML += '<table class="info-table"><tr><th>更新日時</th><td>' + update.getFullYear() + '/' + ('0' + (update.getMonth() + 1)).slice(-2) + '/' + ('0' + update.getDate()).slice(-2) + ' ' + ('0' + update.getHours()).slice(-2) + ':' + ('0' + update.getMinutes()).slice(-2) + '</td></tr>';
    infoHTML += '<tr><th>運営者</th><td><a target="_blank" href="' + profurl + '">' + author + '</a></td></tr>';
    infoHTML += '<tr><th>総投稿数</th><td>' + posttotal + '</td></tr>';
    infoHTML += '<tr><th>最終投稿日</th><td>' + pdate.getFullYear() + '/' + ('0' + (pdate.getMonth() + 1)).slice(-2) + '/' + ('0' + pdate.getDate()).slice(-2) + '</td></tr></table>';
    if (json.feed.category) {
      infoHTML += '<p>カテゴリー(上位' + catnum + '件)</p><div class="p-category">';
      for (var i = 0; i < catnum; i++) {
        infoHTML += '<span>' + Category[i] + '</span>';
      }
      infoHTML += '</div>';
    }
    infoHTML += '<p>最新の投稿' + rpnum + '件</p>';
    if (postTitle.length < rpnum) {
      for (var i = 0; i < postTitle.length; i++) {
        pdate = new Date(postDate[i]);
      	infoHTML += '<a class="rp-link" target="_blank" href="' + postUrl[i] + '"><img class="rp-eyecatch" src="' + postImg[i] + '"/><div class="rp-body"><p class="rp-title">' + postTitle[i] + '</p><span class="rp-date">' + pdate.getFullYear() + '/' + ('0' + (pdate.getMonth() + 1)).slice(-2) + '/' + ('0' + pdate.getDate()).slice(-2) + '</span></div></a>';
      }
    } else {
      for (var i = 0; i < rpnum; i++) {
        pdate = new Date(postDate[i]);
        infoHTML += '<a class="rp-link" target="_blank" href="' + postUrl[i] + '"><img class="rp-eyecatch" src="' + postImg[i] + '"/><div class="rp-body"><p class="rp-title">' + postTitle[i] + '</p><span class="rp-date">' + pdate.getFullYear() + '/' + ('0' + (pdate.getMonth() + 1)).slice(-2) + '/' + ('0' + pdate.getDate()).slice(-2) + '</span></div></a>';
      }
    }
    infoHTML += '</div>';
    
    document.getElementById("blog-info").innerHTML = infoHTML;
  }
  
  function confirm() {
    if (flag == 0 && !document.getElementById("blog-info").innerHTML) {
      document.getElementById("blog-info").innerHTML = '<div class="feed-error">フィード情報を取得できませんでした</div>';
    } else {
      clearInterval(timer);
    }
  }
</script>
<style>
  .info-wrapper {
    padding: 1em;
    border: 2px solid #eee;
    margin-top: 2em;
  }
  
  .feed-error {
    text-align: center;
    background: #ffe4e1;
    padding: 1em;
    margin-top: 2em;
  }
  
  .blog-title {
    font-size: 1.3em;
    font-weight: bold;
    text-align: center;
    margin: 0.5em 0 1.5em;
  }
  
  .info-table {
    width: 100%;
    margin: 0 auto 2em;
    border-collapse: collapse;
  }
  
  .info-table th, .info-table td {
    vertical-align: middle;
    padding: 10px 15px;
    border: 1px solid #d0dbe6;
    box-sizing: border-box;
  }
  
  .info-table th {
    width: 20%;
    background: #f3fcff;
  }
  
  .p-category {
    margin-bottom: 2em;
  }
  
  .p-category span {
    display: inline-flex;
    justify-content: center;
    align-items: center;
    font-size: 0.8em;
    line-height: 1.5;
    padding: 5px 10px;
    margin: 0 0.5em 0.5em 0;
    border: 1px solid #ddd;
    border-radius: 5px;
  }
  
  .rp-link {
    display: flex;
    color: #444 !important;
    max-width: 500px;
    border: 1px solid #ccc;
    border-radius: 10px;
    box-sizing: border-box;
    margin-bottom: 1em;
    transition: 0.5s;
  }
  
  .rp-link:hover {
    text-decoration: none;
    background: #efefef;
  }
  
  .rp-eyecatch {
    display: block;
    width: 100px;
    height: 100px !important;
    object-fit: cover;
    padding: 0 !important;
    margin: 0 !important;
    border: none !important;
    border-radius: 10px 0 0 10px;
    box-shadow: none !important;
  }
  
  .rp-body {
    display: flex;
    flex-direction: column;
    justify-content: space-around;
    height: 100px;
    line-height: 1.5;
    padding: 0.5em;
    box-sizing: border-box;
    word-break: break-all;
    overflow: hidden;
  }
  
  .rp-title {
    font-size: 14px;
    margin: 0 !important;
  }
  
  .rp-date {
    font-size: 12px;
    color: #777;
  }
</style>

表示カテゴリー数、投稿数はお好きな値に設定できます。

解説

コードについての解説です。興味のある人は読んでみてください。

今回は入力したURLをもとにフィードを取得するため、一度フィード用のURLを整形しています。

var feedurl = '//' + url + '/feeds/posts/default?alt=json-in-script&callback=getdata';

それをsrcに入れたスクリプトをリアルタイムでblog-infoの後ろに作り、一瞬で読み込ませてremoveで即消すという仕掛け。ちょっと面倒くさいですが、こうしないとコールバック付きのフィードを送信して関数を正しく呼び出せないのです。

var scr = document.createElement('script');
scr.setAttribute('type', 'text/javascript');
scr.setAttribute('src', feedurl);
document.getElementById("blog-info").after(scr); // スクリプトタグをリアルタイム生成
scr.remove(); // 即削除

その後はsetIntervalで関数confirmを定期実行し、フィード情報がちゃんと取得できているか確認します。ここのエラー処理がなかなか思い通りにいかず、沼りました。

フィードが取得できたらgetdata部分でいろいろと情報をあさり、格納したデータもろもろをHTMLとして整形してblog-info内に書き込みます。これでめでたく表示完了です。

function getdata(json){
  ...
  document.getElementById("blog-info").innerHTML = infoHTML;
}

ちなみに、フィード取得の判定にはフラグflagを使用しています。checkを押した時点で値を0にセットし、フィードが取得できればgetdata内で値を1にセット。こうすると、状態別にうまく処理を切り替えられます。

余談

JavaScriptでいろいろ実験するとき、開発者タブのコンソールを使うとめちゃくちゃ便利でした。console.log()なんかで変数の情報も簡単に確認できます。

2件のコメント
更新日時は何を意味するのでしょうか?
コメントありがとうございます。
更新日時はブログの更新日時のことですね。具体的には、Bloggerにログインした瞬間の時刻を表します。