0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AIをつかってフォームを自動入力させてみる

Posted at

※この記事は、一部AI(ChatGPT)を活用して内容を整理・執筆しています。


☑ これは何?

登録フォームって、オートコンプリートがうまく働かないことありますよね?

  • 郵便番号が2つの入力段に分かれている
  • 電話番号が tel1, tel2, tel3 に分割されている
  • input の name 属性が自動入力に適してない

こんなときに、"AIにHTMLを読ませて、構造を理解させ、適切な入力値を自動表示"させるスクリプトをTampermonkeyで作ってみました。
なお、このスクリプト自体の設計・改善にもAI(ChatGPT)を活用しており、プロンプト設計や分岐条件の調整などはAIと対話しながら進めました。


👉 動作の概要

  • formタグを検出したときに、「🧠 AI自動入力」ボタンを上部に追加
  • ボタンを押すと、LLM (ChatGPT)がform構造を分析
  • name/id/placeholder などを判断し、適切な値を各フィールドに自動入力

🎓 技術構成

  • 実装言語: JavaScript (Tampermonkey)
  • 外部AI: OpenAI GPT-4o
  • DOM分析: form.outerHTMLをLLMに送信
  • レスポンスはJSONで返される[{selector, value}, ...] の配列

☑ できること

  • 任意のフォームに対応 (input nameが常に同じでなくてもセレクタ解釈で対応)
  • 電話番号や郵便番号の分割にも自動対応
  • フォームの内容を判定して、個人情報だけに限定表示

コード一覧

クリックで表示
// ==UserScript==
// @name         Smart Form AutoFill (LLM powered)
// @namespace    http://tampermonkey.net/
// @version      0.4
// @description  フォームにAI自動入力ボタンを追加し、ChatGPTを使って入力補完する
// @author       example
// @match        *://*/*
// @grant        none
// ==/UserScript==

(async function () {
  'use strict';

  const profile = {
    firstName: "Taro",
    lastName: "Yamada",
    fullName: "山田 太郎",
    email: "example@example.com",
    postalCode: "123-4567",
    postalCode1: "123",
    postalCode2: "4567",
    address: "東京都新宿区西新宿1-1-1",
    phone: "080-1234-5678",
    phone1: "080",
    phone2: "1234",
    phone3: "5678"
  };

  const apiKey = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // ← ここにOpenAIのAPIキーを入力

  function isPersonalInfoForm(form) {
    const keywords = ['name', 'fullname', 'email', 'mail', 'address', 'tel', 'phone', 'postcode', 'zip'];
    const inputs = form.querySelectorAll('input, textarea, select');
    return [...inputs].some(input =>
      keywords.some(kw =>
        (input.name && input.name.toLowerCase().includes(kw)) ||
        (input.id && input.id.toLowerCase().includes(kw)) ||
        (input.placeholder && input.placeholder.toLowerCase().includes(kw))
      )
    );
  }

  function createButton(form) {
    const button = document.createElement('button');
    button.textContent = "🧠 AI自動入力";
    button.style.marginBottom = '10px';
    button.style.padding = '6px 12px';
    button.style.fontSize = '14px';
    button.style.cursor = 'pointer';
    button.style.backgroundColor = '#4CAF50';
    button.style.color = 'white';
    button.style.border = 'none';
    button.style.borderRadius = '4px';

    button.addEventListener('click', async (e) => {
      e.preventDefault();
      button.disabled = true;
      button.textContent = '🤖 入力中...';

      const html = form.outerHTML;

      const response = await fetch("https://api.openai.com/v1/chat/completions", {
        method: "POST",
        headers: {
          "Authorization": `Bearer ${apiKey}`,
          "Content-Type": "application/json"
        },
        body: JSON.stringify({
          model: "gpt-4o",
          messages: [
            {
              role: "system",
              content: `あなたはHTMLフォーム入力補助AIです。以下のフォームHTML構造とユーザープロファイルを元に、各入力フィールドへ値を適切にマッピングしてください。
・セレクタはCSSセレクタとして指定してください
・住所・電話番号・郵便番号が複数フィールドに分かれている場合、それぞれ分割して対応してください(例:080-1234-5678 → tel1, tel2, tel3)
・形式は絶対に JSON のみで、マークダウンや記号(\`\`\`)を含めないでください
・出力形式は:[ {"selector": ..., "value": ...}, ... ] のみを返してください`
            },
            {
              role: "user",
              content: `HTMLフォーム:\n${html}\n\nユーザープロファイル:\n${JSON.stringify(profile)}`
            }
          ],
          temperature: 0.2
        })
      });

      const result = await response.json();
      const content = result.choices?.[0]?.message?.content;
      console.log("LLM Response:", content);

      try {
        const cleaned = content.replace(/```[\s\S]*?\n/, '').replace(/```$/g, '').replace(/```/g, '').trim();
        const mappings = JSON.parse(cleaned);
        for (const { selector, value } of mappings) {
          const el = document.querySelector(selector);
          if (el) el.value = value;
          else console.warn(`セレクタ "${selector}" の要素が見つかりませんでした`);
        }
        button.textContent = '✅ 入力完了';
      } catch (err) {
        button.textContent = '⚠️ エラー';
        alert("LLMの出力のパースに失敗しました。コンソールを確認してください。");
        console.error(err);
      }

      setTimeout(() => {
        button.disabled = false;
        button.textContent = "🧠 AI自動入力";
      }, 3000);
    });

    form.parentNode.insertBefore(button, form);
  }

  const forms = document.querySelectorAll('form');
  forms.forEach(form => {
    if (isPersonalInfoForm(form)) {
      createButton(form);
    }
  });
})();


下記のような情報にはボタンは表示されません

  • Qiitaのログインフォーム (user/passwordのみ)
  • 検索フォーム

input[name] などに name, mail, tel, address などのキーワードが含まれる場合のみ表示


作りたい人へ

  • Tampermonkey をChromeに追加
  • 新規スクリプトを作成
  • APIキーを設定
  • フォームのあるページを開けばOK

今後の拡張案

  • プロファイル切替 (自宅用/仕事用)
  • Undo ボタン追加
  • AIの出力をデバッグ表示

まとめ

「言語や構造の振れのあるフォームに、文脈から適切に入力値を埋める」

これはLLMの特技を活かした、一般ユーザーでも使える実用的アプローチでした。

最初は自分用に作ったのですが、他の人も便利になる可能性を感じたので、よかったら試してみてください。

ご意見や改善案も歓迎です!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?