【Blogger】ラベルの付いていない投稿を検索する

Blogger で特定のラベルの付いた投稿だけを表示させるには、以下のような URL を使います。

https://[ブログ名].blogspot.com/search/label/[ラベル名]

では、ラベルの付いていない投稿を検索(抽出)したい場合、どうすればいいのでしょうか?

残念ながら、Blogger にはラベルが付いていない投稿を直接検索する公式の機能はありません。そのため、Blogger ダッシュボードの「投稿」ページを一つ一つスクロールして確認するのがいちばん手っ取り早い方法です。

小規模なブログであればこの方法でもさほど苦労はしませんが、投稿数が増えてくると話は別です。数百、数千と投稿があるなかでラベルの付いていない投稿だけを手作業で探すのは非効率ですし、想像するだけで気が遠くなります。

そこで、ラベルの付いていない投稿を検索する別の方法を考えてみました。

アイキャッチ
この記事の目次

方法1:ブログ検索を使う

Blogger では、ブログに設置されている検索ボックスや、以下のようにブログ URL に続けて検索語句を加えることでブログ検索を利用できます。

https://[ブログ名].blogspot.com/search?q=[検索語句]

ブログ検索では通常の検索語句に加え、ラベル検索も行えます。

以下のような URL を使うと、この記事の冒頭で紹介したラベル検索の URL と同じ検索結果が得られます。by-date=true は検索結果を新着順に並べるパラメータです。

https://[ブログ名].blogspot.com/search?q=label:[ラベル名]&by-date=true

例えば Google Blogger のように、単語の間にスペースを含むラベル名の場合は、半角二重引用符 " で挟んで label:"Google Blogger" とします。もちろん、スペースを含まないラベル名も " で挟んでオッケーです。

さらに、以下のように NOT、AND、OR 演算子を使うことで、特定のラベルの追加や除外ができます。

  • NOT 検索:特定のラベルを持たない投稿を検索

    -label:[ラベル名]

  • AND 検索:複数のラベルが付いた投稿を検索

    label:[ラベル名1]+label:[ラベル名2](検索ボックスを使う場合 + を半角スペースに置き換える)

  • OR 検索:いずれかのラベルが付いた投稿を検索

    label:[ラベル名1]|label:[ラベル名2]

このうち NOT 検索とAND 検索を組み合わせ、以下のようにしてブログに存在する全てのラベルを除外することで、ラベルの付いていない投稿を抽出することができます。

-label:[ラベル名1]+-label:[ラベル名2]+-label:[ラベル名3]+-label:[ラベル名4]+...

(検索ボックスを使う場合 + を半角スペースに置き換えてください)

とはいえ、全てのラベルの除外作業を手動で行うのはそれこそ骨が折れるので、自動で検索ワードを生成する方法を考えました。

以下のコードを、全てのラベルを表示したラベルウィジェットの b:includable id='main' 内の他のコードに干渉しない場所に設置し、保存します。

<b:loop values='data:labels' var='label'>-label:"<data:label.name.escaped/>"+</b:loop>

これにより生成された検索語句を検索ボックス、またはブログ検索のURLに設定することで、瞬時にラベルのない投稿が検索できます。

ただし、ラベル名に特殊文字が含まれていると検索がうまく機能しません。筆者がテストした限りでは、ラベル名に "+#&(全て半角) を含むラベル名の場合、正しい検索結果が得られないことがありました。

さらに、ラベル総数が多いブログだとブラウザによっては URL の文字数制限に引っかかるおそれもあります。ラベルが少なく、かつラベル名に特殊文字が含まれていないブログであれば充分使える方法だと思います。

方法2:フィードを使う

ブログ検索ではラベルの付いていない投稿の抽出がうまくいかないケースがあるため、フィードを利用してラベルのない投稿を取得する方法を考えました。

以下のコードを、Blogger の投稿またはページの編集エディタに貼り付けてください。

<div class="unlabeled-posts">Now Loading...</div>

<script>//<![CDATA[
async function getUnlabeled() {
  // ラベルのない投稿を格納する配列を初期化
  const unlabeledPosts = [];
  // 1回のリクエストで取得する最大の投稿数を設定
  const maxResults = 150;
  // 投稿の総数と開始インデックスを初期化
  let totalResults = 0;
  let startIndex = 1;
  let blogId = '';  // ブログIDを格納する変数

  // 投稿を取得し続けるためのループ
  do {
    // 投稿フィードのURLを生成(JSON形式で取得)
    const feedUrl = `/feeds/posts/summary?alt=json&start-index=${startIndex}&max-results=${maxResults}`;
    // APIリクエストを送信して、レスポンスをJSONとして取得
    const response = await fetch(feedUrl);
    const json = await response.json();

    // 最初のリクエスト時に総投稿数とブログIDを設定
    if (startIndex === 1) {
      totalResults = Number(json.feed.openSearch$totalResults.$t);
      blogId = json.feed.id.$t.split('-').pop();
    }

    // 各投稿についてループ処理
    json.feed.entry.forEach(entry => {
      // カテゴリ(ラベル)がない投稿をフィルタリング
      if (!entry.category) {
        // 投稿ID、タイトル、公開日、URL、サムネイルを取得
        const id = entry.id.$t.split('-').pop();
        const title = entry.title.$t;
        const date = entry.published.$t.slice(0, 10).replace(/-/g, '/');
        const url = entry.link.find(link => link.rel === 'alternate').href;
        const thumbnail = entry.media$thumbnail ? entry.media$thumbnail.url : '//resources.blogblog.com/img/blank.gif';
        // 投稿情報をオブジェクトとして配列に追加
        unlabeledPosts.push({ id, title, date, url, thumbnail });
      }
    });

    // 次のリクエストのために開始インデックスを更新
    startIndex = startIndex + maxResults;
  } while (startIndex <= totalResults); // すべての投稿を取得するまで繰り返す

  // ラベルのない投稿が存在しない場合の処理
  if (unlabeledPosts.length === 0) {
    document.querySelector('.unlabeled-posts').innerHTML = 'ラベルの付いていない投稿はありません。';
  } else {
    // ラベルのない投稿が存在する場合、デバッグ用にコンソールログ表示
    console.log(JSON.stringify(unlabeledPosts, false, 2));
    // ラベルのない投稿を画面に表示
    displayUnlabeled(blogId, unlabeledPosts);
  }
}

// ラベルのない投稿をHTMLとして表示する関数
function displayUnlabeled(blogId, posts) {
  // 投稿数を表示するHTMLの初期化
  let html = `<p>ラベルの付いていない投稿:${posts.length} 件</p><ul>`;

  // 各投稿をリストとしてHTMLに追加
  posts.forEach(post => {
    html += `<li><a href="${post.url}" target="_blank">${post.title}</a>(${post.date})</li>`;
  });

  // リストの閉じタグを追加
  html += '</ul>';
  // 指定の要素に生成したHTMLを挿入
  document.querySelector('.unlabeled-posts').innerHTML = html;
}

// getUnlabeled関数を実行して、ラベルのない投稿を取得
getUnlabeled();
//]]></script>

この JavaScript コードは2つの関数 getUnlabeled()displayUnlabeled() で構成されています。

関数 getUnlabeled() では、ラベルのない投稿のデータを配列 unlabeledPosts に格納します。

Blogger の投稿フィードから1度に取得できる最大投稿数は150件なので、全投稿数が151件を超える場合複数のリクエストで全投稿を取得します。その処理は以下の記事を参考にしました。

投稿にラベルが付いていないかどうかは json.feed.entry.category が存在しないかで確認し、ラベルのない投稿のデータだけを配列に追加していきます。

全投稿分のフィードの処理が終わったら、ラベルのない投稿が存在しないときはその旨を伝えるメッセージを表示して処理を終了し、ラベルがない投稿が存在するときはブラウザのデベロッパーツールのコンソールログに unlabeledPosts の内容を表示し、関数 getUnlabeled() に進みます。

関数 getUnlabeled() では、ラベルのない投稿をリストとして HTML 上に表示します。上記のコードの場合、投稿へのリンクと投稿日が出力されます。

サムネイルを表示させたい場合は、以下のようなコードを追加します。

html += `<img alt="${post.title}" src="${post.thumbnail}" width="72"/>`;

また、投稿の編集リンクを生成したい場合は、ブログ ID と投稿 ID を使って次のように記述できます。

html += `<a href="https://www.blogger.com/blog/post/edit/${blogId}/${post.id}" target="_blank">編集</a>`;

投稿数が多いブログでは時間がかかることがありますが、ブログにラベルが多すぎる場合やラベルに特殊文字が含まれる場合にも、この方法であればその影響を受けずにラベルのない投稿を正確に取得できます。

あとがき

Blogger にはラベルの付いていない投稿を検索する機能がないため、ブログ検索やフィードを利用して効率よくラベルのない投稿を抽出する方法を紹介しました。

ラベルを付けていない投稿にラベルを付けたくても、投稿数が多いブログゆえに諦めていた方もいたのではと思います。そんな方にも、もちろんそれ以外の方にもこの記事が参考になれば幸いです。

編集
ホーム