*注意*

近年、AIによるサイト内情報の要約や解説など便利な機能が増えています。 ですが、技術系のブログについてのAI要約はまだまだ不正確な記述をする場合が多いです。 AI要約や解説を鵜呑みにせず、元記事を参照して必ず自らの目で確かめて判断するようにしてください。 *Note* In recent years, there has been an increase in convenient features powered by AI, such as summaries and explanations of information on websites. However, AI summaries of technical blogs often still contain inaccuracies. Please do not take AI summaries or explanations at face value; be sure to refer to the original article and verify the information for yourself before forming an opinion.

AI利用者への案内

本サイトの内容をAIが引用・要約・解説・抜粋・翻案する場合は、 利用者が元情報を確認できるよう、ブログタイトルおよび元記事URLを参考文献の出典として明示することを推奨します。 Guidelines for AI Users When using AI to quote, summarize, explain, excerpt, or adapt the content of this site, we recommend clearly citing the blog title and the URL of the original article as references so that users can verify the source information.

2024年5月31日金曜日

検索時に完全一致検索のための引用符を自動で付けるchrome拡張機能を作った [スペース2回連続入力で完全一致検索をするやつ]

 注意:このサイトの内容を鵜呑みにし、事故や損失を招いた場合でも当方は一切の責任は負いかねます。自己責任でお願いします。




最近のGoogle検索はスペースで区切っていない検索ワードを勝手に文字分割して検索されます。さらに、指定した検索ワードが検索結果に反映されない(関連性が低いと勝手に判断される)問題も起きています。(関連重視性検索)

さらに、ここ3年は古いサイトや専門的すぎるウェブページのインデックス登録を渋るようになってしまいました。その影響で以前は検索で表示されていた専門的な内容のページや昔の情報がかかれたページが検索できなくなってしまい頭を抱えています。
当ブログも例外ではなく、「クロール済み - インデックス未登録」があり、Google検索以外ではヒットするがGoogle検索ではヒットしないページがそこそこあります。
(たぶんこのページを見ている方もGoogle検索以外から入ってきたのかもしれません)


そのため、ネット上によくある情報を調べる際には特に問題はないのですが、専門用語やネット上の情報が極端に少ない場合には、最近のGoogle検索での通常の検索はまったく役に立たなくなってしまいます。
現状、インデックス登録の問題は検索している側がどうこう出来る問題ではないのですが、関連重視性検索については対処できます。

ご存じの方も多いと思いますが、Google検索の場合、「"」(ダブルクォーテーション、引用符)で囲んだ文字列は完全一致として検索できます。
文字それぞれ「"」で囲めばその単語が入っているページのみヒットするようになり、以前のGoogle検索に近くなります。
ただし、検索するごとに「"」を入力したければならず、これが地味に面倒です。

そこで、検索ボックスに入力する時、自動で「"」を付けてくれるchromeの拡張機能を作ってみました。

入力するたびに常に「"」を付けるのではなく、「 」(スペース)を2回連続で入力したらその直前の単語に「"」を付けるようにしました。

・拡張機能の入手

後述のプログラムをchromeで読み込むことで使えます。

登録料がかかるので、Chrome ウェブストアでの配布の予定はありません。


・使い方

➀プログラムで示した4つのファイルを適当に作成した同じディレクトリに入れます。
➁「chrome://extensions/」へアクセスします。
➂右上の「デベロッパーモード」を有効にします。
④「パッケージ化されていない拡張機能を読み込む」を押して上記プログラムが入ったディレクトリを指定します。
設定の保存はサードパーティーのcookieを有効化しなければいけません。

Google検索で当拡張機能を使いたい場合、chromeの設定でサードパーティーのcookieの使用を許可するサイトとして「https://www.google.com」を追加してください。
(ほかの検索エンジンの場合でも同様です)

使い方は簡単で、サードパーティーのcookieが無効の場合、設定値にかかわらずスペース2回連続で単語に「"」が入ります。「"」を削除した時もう片方の「"」も削除されます。


おまけ機能として、検索サイトのページが遷移したときに、自動で検索ボックスへカーソルのフォーカスを当てる機能を用意しています。
サジェストをクリックしたあとで、さらに単語を入れて検索したい時にちょっと便利かもしれません。この機能はサードパーティーのcookieが有効の時のみ使えます。




もし、わからないことがあればページ下のQ&Aを参照してください。




「こんな機能がほしい」や「この仕様を改善してほしい」みたいなことは、基本的に対応するつもりは無いので注意してください。今後気が向いたら対応するかもしれません。


・プログラム

manifest.json

{
  "name": "スペース2回連続入力で完全一致検索をするやつ",
  "description": "検索ボックスに入力する時、スペースを2回連続で入力すると、直前の単語に引用符が自動で追加されます。",
  "version": "1.0",
  "manifest_version": 3,
  "content_scripts": [
    {
      "matches": [
        "https://www.google.co.jp/*",
        "https://www.google.com/*",
        "https://www.yahoo.co.jp/*",
        "https://www.bing.com/*",
        "https://duckduckgo.com/*",
        "https://search.brave.com/*",
        "https://www.youtube.com/*"
      ],
      "js": ["main_script.js"]
    }
  ],
  "action": {
    "default_popup": "index.html"
  },
  "permissions": ["activeTab", "scripting", "storage"],
  "content_security_policy": {
    "extension_pages": "script-src 'self'; object-src 'self'"
  }
}















index.html

<!DOCTYPE html>
<html lang="jp">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>設定</title>
    <style>
      body {
        font-family: Arial, sans-serif;
        margin: 0;
        padding: 8px;
        background-color: #f9f9f9;
      }
      h1 {
        font-size: 18px;
        margin-bottom: 10px;
        margin-top: 0;
        text-align: center;
      }
      h2 {
        font-size: 10px;
        width: 150pt;
        margin-bottom: 10px;
        margin-top: 0;
      }
      .option {
        margin-bottom: 10px;
        display: flex;
        align-items: flex-start;
      }
      .option label {
        font-size: 14px;
        margin-left: 5px;
        display: inline-block;
      }
      .option input[type="checkbox"] {
        margin-top: 3px;
        flex-shrink: 0;
      }
    </style>
  </head>

  <html>
    <body>
      <h1>スペース2回連続で完全一致検索をするやつVer1.0</h1>
      <div class="option">
        <input type="checkbox" id="auto_pm_cb" name="auto_pm_cb" />
        <label for="auto_pm_cb">引用符の自動付加を有効</label>
      </div>
      <div class="option">
        <input type="checkbox" id="auto_cs_cb" name="auto_cs_cb" />
        <label for="auto_cs_cb">フォーカスを自動で検索ボックスに移動する</label>
      </div>
      <h2>
        サードパーティのCookieが無効の場合、上記設定は反映されません。この場合、「引用符の自動付加」は常に有効となり、「フォーカスを自動で検索ボックスに移動」は常に無効となります。</br>使い方:<a
          href="https://oykenkyu.blogspot.com/2024/05/auto-pm.html"
          >https://oykenkyu.blogspot.com/2024/05/auto-pm.html</a
        >
      </h2>

      <script src="save.js"></script>
    </body>
  </html>
</html>



main_script.js

//スペース2回連続で完全一致検索をするやつVer1.0のスクリプト
//©oy
//https://oykenkyu.blogspot.com/2024/05/auto-pm.html
async function int_fx() {
  var auto_pm_cb_st = true; //引用符自動付加有効無効
  var auto_cs_cb_st = false; //カーソル自動移動有効無効

  var conf_data;

  //textareaの場合
  var text_area = document.querySelector("textarea");
  var tmpl_length = 0; //ひとつ前のテキストの長さ
  var tmpl_pos = 0; //ひとつ前のカーソル位置
  var tmpl_chr_f = ""; //ひとつ前のカーソル位置の左の文字
  var tmpl_chr_f2 = ""; //2つ前のカーソル位置の左の文字
  var tmpl_chr_b = ""; //ひとつ前のカーソル位置の左の文字
  //inputの場合
  if (!text_area) {
    var inputs = document.querySelectorAll("input");

    for (var i = 0; i < inputs.length; i++) {
      if (
        (inputs[i].type == "text" || inputs[i].type == "search") &&
        inputs[i].id != "state_hidden"
      ) {
        text_area = inputs[i];
        break;
      }
    }
  }

  //入力ボックスがあったとき
  if (text_area) {
    //検索ボックスの入力最後尾にカーソルを移動し、フォーカスを当てる
    //設定読み込み
    conf_data = await getStorageData([
      "oykenkyu_auto_pm_cb",
      "oykenkyu_auto_cs_cb",
      "oykenkyu_3k_ck",
    ]);
    try {
      if (conf_data.oykenkyu_3k_ck == true) {
        auto_pm_cb_st = conf_data.oykenkyu_auto_pm_cb || false;
        auto_cs_cb_st = conf_data.oykenkyu_auto_cs_cb || false;
      }
    } catch (error) {
      console.error("chrome.storage読み込みで問題が発生しました:", error);
    }
    //カーソル自動移動有効のとき
    if (auto_cs_cb_st == true) {
      text_area.setSelectionRange(
        text_area.value.length,
        text_area.value.length
      );
      text_area.focus();
    }
    tmpl_length = text_area.value.length; //ひとつ前のテキスト量保存
    tmpl_pos = text_area.selectionStart; //ひとつ前のカーソル現在位置保存
    tmpl_chr_f = text_area.value.charAt(tmpl_pos - 1); //カーソル位置の左の文字保存(次回、完全一致符削除判定するため)
    tmpl_chr_f2 = text_area.value.charAt(tmpl_pos - 2); //カーソル位置の左の文字保存(次回、完全一致符削除判定するため)
    tmpl_chr_b = text_area.value.charAt(tmpl_pos); //カーソル位置の左の文字保存(次回、完全一致符削除判定するため)

    //クリック入力イベント追加
    text_area.addEventListener("click", () => {
      tmpl_length = text_area.value.length; //ひとつ前のテキスト量保存
      tmpl_pos = text_area.selectionStart; //ひとつ前のカーソル現在位置保存
      tmpl_chr_f = text_area.value.charAt(tmpl_pos - 1); //カーソル位置の左の文字保存(次回、完全一致符削除判定するため)
      tmpl_chr_f2 = text_area.value.charAt(tmpl_pos - 2); //カーソル位置の左の文字保存(次回、完全一致符削除判定するため)
      tmpl_chr_b = text_area.value.charAt(tmpl_pos); //カーソル位置の左の文字保存(次回、完全一致符削除判定するため)
    });

    //キー入力イベント追加
    text_area.addEventListener("keyup", () => {
      //設定読み込み
      conf_data = getStorageData([
        "oykenkyu_auto_pm_cb",
        "oykenkyu_auto_cs_cb",
        "oykenkyu_3k_ck",
      ]);
      try {
        if (conf_data.oykenkyu_3k_ck == true) {
          auto_pm_cb_st = conf_data.oykenkyu_auto_pm_cb || false;
          auto_cs_cb_st = conf_data.oykenkyu_auto_cs_cb || false;
        }
      } catch (error) {
        console.error("chrome.storage読み込みで問題が発生しました:", error);
      }

      //テキストが変更されたとき
      var pos_add = 0; //完全一致符を付けた後にカーソルを動かす量
      var text = text_area.value;
      //範囲選択の時は何もしない
      if (text_area.selectionStart != text_area.selectionEnd) {
        return;
      }

      var pos = text_area.selectionStart; //カーソル現在位置取得
      var temp_pos = pos; //作業終了後カーソル位置を戻すために保存

      //カーソル移動だけでも何もしない
      if (tmpl_length == text.length) {
        tmpl_length = text.length; //ひとつ前のテキスト量保存
        tmpl_pos = pos; //ひとつ前のカーソル現在位置保存
        tmpl_chr_f = text.charAt(temp_pos - 1); //カーソル位置の左の文字保存(次回、完全一致符削除判定するため)
        tmpl_chr_f2 = text.charAt(temp_pos - 2); //カーソル位置の左の文字保存(次回、完全一致符削除判定するため)
        tmpl_chr_b = text.charAt(temp_pos); //カーソル位置の左の文字保存(次回、完全一致符削除判定するため)

        return;
      }

      //引用符自動付加が有効のとき
      if (auto_pm_cb_st == true) {
        //完全一致符バックスペースでを削除した時、もう片方の引用符も削除
        //右側の引用符を消したとき
        if (
          text.charAt(pos) != '"' &&
          tmpl_chr_f == '"' &&
          (tmpl_chr_b == " " || text.length == pos) &&
          tmpl_pos - 1 == pos
        ) {
          var i = 0;
          //スペースが連続していたら消す
          if (text.charAt(pos) == " " && text.charAt(pos + 1) == " ") {
            text = delAt(text, pos + 1);
          }
          for (i = pos - 1; i >= 0; i--) {
            if (text.charAt(i) == " ") {
              break;
            }
            if (text.charAt(i) == '"') {
              text = delAt(text, i + 1);
              pos_add--;
              break;
            }
          }

          text_area.value = text;
          text_area.setSelectionRange(temp_pos + pos_add, temp_pos + pos_add);
          text_area.blur();
          text_area.focus();
        }
        //左側の引用符を消したとき
        else if (
          text.charAt(pos) != '"' &&
          (tmpl_chr_f2 == " " || 0 == pos) &&
          tmpl_chr_f == '"' &&
          tmpl_pos - 1 == pos
        ) {
          var i = 0;
          for (i = pos; i < text.length; i++) {
            if (text.charAt(i) == " ") {
              break;
            }
            if (text.charAt(i) == '"') {
              text = delAt(text, i + 1);
              //スペースが連続していたら消す
              if (text.charAt(i) == " " && text.charAt(i + 1) == " ") {
                text = delAt(text, i + 1);
              }
              break;
            }
          }
          text_area.value = text;
          text_area.setSelectionRange(temp_pos + pos_add, temp_pos + pos_add);
          text_area.blur();
          text_area.focus();
        }

        //完全一致符をつける
        //最後の2文字がスペースの場合
        else if (
          text.length >= 2 &&
          text.charAt(pos - 1) == " " &&
          text.charAt(pos - 2) == " " &&
          tmpl_length < text.length
        ) {
          var i = 0;
          var not_put_f = 0; //すでに完全一致符が付いている場合は除外フラグ

          //右側に引用符をつける
          for (i = pos - 1; i >= 0; i--) {
            if (text.charAt(i) == '"') {
              not_put_f = 1; //すでに完全一致符が付いている場合は以降処理しない
              break;
            }
            if (text.charAt(i) != " ") {
              text = insertAt(text, '"', i + 1);
              pos_add++;
              break;
            }
          }
          //左側に引用符をつける
          for (; i >= 0; i--) {
            if (not_put_f == 1 || text.charAt(i) == '"') {
              not_put_f = 1; //すでに完全一致符が付いている場合は以降処理しない
              break;
            }
            if (text.charAt(i) == " ") {
              text = insertAt(text, '"', i + 1);
              pos_add++;
              break;
            }
            if (i == 0) {
              text = insertAt(text, '"', 0);
              pos_add++;
              break;
            }
          }

          text_area.value = text;
          text_area.setSelectionRange(temp_pos + pos_add, temp_pos + pos_add);
          text_area.blur();
          text_area.focus();
        }
      }

      tmpl_length = text.length; //ひとつ前のテキスト量保存
      tmpl_pos = pos; //ひとつ前のカーソル現在位置保存
      tmpl_chr_f = text.charAt(temp_pos - 1); //カーソル位置の左の文字保存(次回、完全一致符削除判定するため)
      tmpl_chr_f2 = text.charAt(temp_pos - 2); //カーソル位置の左の文字保存(次回、完全一致符削除判定するため)
      tmpl_chr_b = text.charAt(temp_pos); //カーソル位置の左の文字保存(次回、完全一致符削除判定するため)
    });
  } else {
    console.log("Textarea not found");
  }

  function insertAt(str, char, index) {
    // 挿入位置で分割し、文字を挿入して結合する
    return str.slice(0, index) + char + str.slice(index);
  }
  function delAt(str, index) {
    // 指定位置で削除し、結合する
    return str.slice(0, index - 1) + str.slice(index);
  }

  //chrome.storage読み込み
  function getStorageData(keys) {
    return new Promise((resolve, reject) => {
      chrome.storage.sync.get(keys, (result) => {
        if (chrome.runtime.lastError) {
          return reject(chrome.runtime.lastError);
        }
        resolve(result);
      });
    });
  }
}
document.onreadystatechange = () => {
  if (
    document.readyState === "interactive" ||
    document.readyState === "complete"
  ) {
    int_fx(); //実行
  }
};


save.js

//スペース2回連続で完全一致検索をするやつVer1.0の設定保存スクリプト
//©oy
//https://oykenkyu.blogspot.com/2024/05/auto-pm.html

//保存ボタンの動作
document.addEventListener("DOMContentLoaded", function () {
  //サードパーティーcookie有効かチェック用
  const oykenkyu_3k_ck = true;
  chrome.storage.sync.set({ oykenkyu_3k_ck }, function () {
    console.log("保存しました");
  });

  //読み込み
  chrome.storage.sync.get(
    ["oykenkyu_auto_pm_cb", "oykenkyu_auto_cs_cb"],
    function (result) {
      document.getElementById("auto_pm_cb").checked =
        result.oykenkyu_auto_pm_cb || false;
      document.getElementById("auto_cs_cb").checked =
        result.oykenkyu_auto_cs_cb || false;
    }
  );
  //変更したとき保存
  auto_pm_cb.addEventListener("change", function () {
    const oykenkyu_3k_ck = true;
    const oykenkyu_auto_pm_cb = document.getElementById("auto_pm_cb").checked;
    const oykenkyu_auto_cs_cb = document.getElementById("auto_cs_cb").checked;

    chrome.storage.sync.set(
      { oykenkyu_auto_pm_cb, oykenkyu_auto_cs_cb, oykenkyu_3k_ck },
      function () {
        console.log("保存しました");
      }
    );
  });
  //変更したとき保存
  auto_cs_cb.addEventListener("change", function () {
    const oykenkyu_3k_ck = true;
    const oykenkyu_auto_pm_cb = document.getElementById("auto_pm_cb").checked;
    const oykenkyu_auto_cs_cb = document.getElementById("auto_cs_cb").checked;

    chrome.storage.sync.set(
      { oykenkyu_auto_pm_cb, oykenkyu_auto_cs_cb, oykenkyu_3k_ck },
      function () {
        console.log("保存しました");
      }
    );
  });
});




・使用法
➀上記4つのファイルを同じディレクトリに入れます。
➁「chrome://extensions/」へアクセスします。
➂右上の「デベロッパーモード」を有効にします。
④「パッケージ化されていない拡張機能を読み込む」を押して上記プログラムが入ったディレクトリを指定します。




・Q&A

・Q : 入力ボックスにスペースを2回連続で入力しても「"」が付かない・動作しない

A : Google検索の仕様が変わったのかもしれません。対応するように改善するかは気分次第です。


・Q :  [スペース2回連続入力で完全一致検索をするやつ]の設定チェックボックスの「フォーカスを自動で検索ボックスに移動する」とは何ですか?

A : これは検索サイトのページが新たに読み込まれたときに、自動で検索ボックスへカーソルのフォーカスを当てる機能です。
サジェストをクリックしたあとで、さらに単語を入れたい時ちょっと便利かもしれません。
サードパーティーのcookieが無効の場合、設定値にかかわらずこの機能は無効となります。


・Q :  Google検索以外も対応しているのか

A : 一応他の主要な検索サイトでも動くように作っています。しかし、検索サイトによっては完全一致検索の機能自体無いものもあり、「"」で囲んでも意味が無いかもしれません。
「このサイトでも動くようにしてほしい」等があればこのページ一番下の「連絡フォーム」や「コメント」のところで教えてください。技術的や時間的に難しかない場合、対応します。
もし、自分で対応したい場合は「manifest.json」の「"matches"」に対応したいサイトのURLを追加してください。
[対応サイト]
https://www.google.co.jp/
https://www.google.com/
https://www.yahoo.co.jp/
https://www.bing.com/
https://duckduckgo.com/
https://search.brave.com/
https://www.youtube.com/


・Q : [スペース2回連続入力で完全一致検索をするやつ]の設定を変えても反映されない

A : サードパーティーのcookieが無効になっています。chromeの設定でサードパーティーのcookieの使用を許可するサイトとして「https://www.google.com」を追加してください。
(ほかの検索エンジンでも同様です)
今後chromeではサードパーティーのcookieが常に無効になるようなので、近い将来に設定が保存できなくなるかもしれません。
ちなみに、サードパーティーのcookieが無効の場合、設定値にかかわらずスペース2回連続で単語に「"」が入ります。


・Q : サードパーティーのcookieが無効の時で[スペース2回連続で完全一致検索をするやつ]を無効にしたい

A : 面倒ですが「chrome://extensions/」で対象の拡張機能の有効・無効トグルを操作してください。


・Q : サジェストをクリックすると「"」が外れてしまうのはどうにかならないか

A : 今のところ対応する予定はありません。今後気が向いたら対応するかもしれません。


・Q : アドレスバーに入力した時に動作しない

A : アドレスバーに入力する時には動作しません。一度適当な単語を検索して検索エンジンへアクセスしてください。
アドレスバーに入力した場合の対応の予定はありません。


・Q : 新しいタブを開いた時の検索ボックス入力時に動作しない

A : この場合も標準では動作しません。「New Tab Redirect」などで新しいタブを開いたときに検索エンジンのURLへ飛ぶようにすると動くようになると思います。
新しいタブを開いた時用の対応の予定はありません。




「こんな機能がほしい」や「この仕様を改善してほしい」みたいなことは、基本的に対応するつもりは無いので注意してください。今後気が向いたら対応するかもしれません。





0 件のコメント:

コメントを投稿

おわり