『7回目の出直し🌻』

好きなことを自分のペースで、のんびり更新

はてなブログの購読リストが使いにくい!120行のスクリプトでサクッときれいにする

久しぶりにはてなブログの不満記事です。

今日は、購読リストが使いにくい件です。

購読リスト

購読リストとはこれです。

自分が読者になっているブログのリストが見えるページです。
購読しているブログに変更があると未読件数を数字で教えてます。また、最近追加された記事が出てくるのでブログをたどりやすいです。

ここまではよい。

問題はここから

今の購読リストは、ここが使いにくいです

  • 自分が購読しているブログの総件数が分からない
  • 購読しているブログを全体を見るページがない(記事が3個ずつ挟まるのが邪魔)
  • 更新があると上に上がってくる仕組みなので、更新がないブログは埋もれてしまう
  • 1ページに10ブログしか表示できないので、たくさん見るときは次ページを連打
  • 「おとなり日記」が挟まるのが邪魔
  • 「次に読者になりたいブログ」も邪魔(new!)

月に1回くらい更新がある友人のページを探すには、「次のページ」でめくっていくゲームになります。これはツライ。

面倒なので、さくっと1ページで見えるようにしたろうじゃないか。という記事です。

使ったもの

JavaScript 120行だけです。

今、開いている画面上で動きます。IDやパスワードを入力して情報を取りに行く仕組みではないので安心してください。
はてなブログの管理画面にログインした状態で実行すればOKです。

コード

コードはこれだけです。

実行前に上のほうに書いてあるmaxpagemaxwindowsの値を書き換えてください。

// ==ClosureCompiler==
// @output_file_name default.js
// @compilation_level SIMPLE_OPTIMIZATIONS
// @language_out ECMASCRIPT_2017
// ==/ClosureCompiler==
javascript: (

  async function (pages,windows) {
    //何ページ目まで繰り返すか、各自で変えてください。
    let maxpage = 5;
    //ボタンのクリックで開くウィンドウの数
    let maxwindows = 5;

    if(Number.isInteger(pages)){
      maxpage=pages;
    }
    if(Number.isInteger(windows)){
      maxwindows=windows;
    }

    const anntena = 'https://blog.hatena.ne.jp/-/antenna';
    if (window.location.href.indexOf("https://blog.hatena.ne.jp/-/antenna") != 0) {
      let ans = confirm('ページが違います。購読リストへ移動します');
      if(ans){
        window.location.href = anntena;
        return;
      }
    }

    $('div.l-admin-subscribe-wrapper-left').remove();
    $('div.l-admin-subscribe-wrapper-right').remove();
    
    const bloglist = [];

    for (let p = 1; p <= maxpage; p++) {
      console.info('page:%s', p);
      updateCaption(`${p}/${maxpage} ページ目`);
      let html = await getHTML(anntena + '?page=' + p);

      let li = $(html).find('li.subscribed-list-list');
      console.log('li count = %s', li.length);

      for (let i = 0; i < li.length; i++) {
        bloglist.push(li[i]);
      }
    }

    updateCaption(`リスト作成中...`);
    console.info('blog count = %s', bloglist.length);

    let summary = "";
    for (let i in bloglist) {
      let ans = parse(bloglist[i]);
      console.log(ans);
      summary += 
        `<div style="display: flex;">
          <div style="width:60px;">
          <img src="${ans.img}" width="48" >
          </div>
          <div style="margin-bottom:10px; width: calc(100% - 60px);">
          <span style="font-size:115%; font-weight:bold">${ans.blogname}</span><br>
          <a href="${ans.link}" target="_blank" rel="noopener noreferrer" class="x_x" data-opened="0">${ans.title}</a> ${ans.jsttime}
          </div>
        </div>`
    }

    updateCaption(bloglist.length);
    $('div.l-admin-subscribe-wrapper').append(summary);

    $('nav.service-nav-actions').prepend(
      `<button class="service-nav-action-item action-item-edit" id="x_x_open">${maxwindows}個のリンクを開く
      <span class="badge badge-new" id="x_x_remains"></span>
      </button>`
    );
    $('#x_x_open').on('click', function(){
      let links = $('a.x_x[data-opened="0"]');
      for(let i=0; i<links.length && i<maxwindows; i++){
        links[i].dataset.opened='1';
        links[i].textContent = '✅'+ links[i].textContent;
        window.open(links[i].href);
      }
      updateButtonCaption();
    });

    updateButtonCaption();

    function updateButtonCaption(text){
      let remains = $('a.x_x[data-opened="0"]').length;
      $('span#x_x_remains').text(remains);
    }
    function updateCaption(text){
      $('h1.antenna-heading').text('購読リスト:' + text);
    }
    //liタグ(ブログ1個分)を解析する
    function parse(li) {
      const target = $(li);
      const blogname = target.find('a.entry-unit-blog-name').text().trim();
      const a = target.find('div.entry-unit-content h3.entry-unit-entry-title > a');
      const title = a.text().trim();
      const link = a.attr('href');
      const time = target.find('div.entry-unit-content div.entry-unit-entry-footer time.entry-unit-post-time');
      const utctime = time.attr('datetime');
      const jsttime = new Date(utctime).toLocaleString();
      const diff = time.text();

      const img = target.find('img.subscribed-list-icon').attr('src');
      return { blogname, title, link, utctime, jsttime, diff, img };
    }

    //HTMLを取りに行く
    async function getHTML(url) {
      const response = await fetch(url);
      const html = await response.text();
      return html;
    }
  }
)(5,5);
修正履歴

■ 2022年7月17日修正
はてなブログの購読リストのレイアウトが変更になったので微調整しました。

■ 2022年11月18日修正
左側に「編集部が選んだブログ」が出てくるのでまとめて削除するようにする。
出力HTMLを変更。リンクを別ウィンドウで開くように変更。

■ 2022年11月19日修正
まとめてリンクを開くボタンを追加。1回で開くリンク数も変更可能に。一度開いたリンクは開かないようにしてある。
ボタンに残りリンク数を表示するように変更。

■ 2022年11月23日修正
実行したページが違うときに、confirmで「はい」「いいえ」を選択するようにした。

GitHubにも置いておきます

コードをコピーするなら、githubからコピーするほうが楽です。

https://raw.githubusercontent.com/kanaxx/hatenablog-omocha/main/subscribe-list/anntena.js

実行方法

Chromeの場合、

  1. 購読リストを開き
  2. F12キーを押してDeveloperツールを開き
  3. コンソール(console)を開き
  4. コードを貼り付けして
  5. ENTERキーを押す

実行結果

実行中の様子を動画で撮りました。
(購読リストに載ってしまっている方、すいません)

右側のコンソールにちょろちょろっとメッセージが出て、5秒後くらいに左側がスッキリします。

リストに表示される項目

情報は最小限に

すっきり後には、自分の購読リストの全体を1ページで表示します。

ブログにごとに

  • アイコン
  • ブログタイトル
  • 1件目の記事とリンク
  • 最終更新日

だけです。

購読数も見えるように

画面の上にある「購読リスト」のタイトル横に件数(147の部分)が表示されます。

リンクを開くボタンを追加

画面の右上にリンクを開くボタンを追加しました。

このボタンを押すと購読リストのリンクが一気に開きます。上から順番に開きます。一回で何個のリンクを開くのかはスクリプトの中で変更できます。

注意事項として

  • 購読リストの量(ページ数)によって、かかる時間に違いがあります。
  • とりに行くページは5ページまでにしてあります。コードの10行目にある数値を変更すると5ページ以上進みます。
  • 購読リストを開くたびに毎回実行しないといけません
  • はてなブログの仕様変更で動かなくなることがあります
  • 何かおきても自己責任でお願いします。

今日のところはこんな感じです。

お役に立てていたら、右側のバナーで何か買っていただけると励みになります。