2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ブラウザ操作を自動キャプチャして手順書を作るChrome拡張の作り方:Procshot開発記録

2
Last updated at Posted at 2026-06-06

はじめに

「この操作、どうやるんでしたっけ?」

社内システムの使い方を聞かれるたびに、スクショを撮って、赤枠つけて、「ここをクリックします」と書いて...。気づけば30分経っている。

この無駄な時間をなくしたくて、ブラウザ操作を自動でキャプチャして手順書を作るChrome拡張機能を作りました。

手順キャプチャ(Procshot)をChrome ウェブストアで見る

作ったもの

手順キャプチャ(英語名: Procshot)

「撮影開始」ボタンを押して普通にブラウザを操作するだけで、スクショ付きの手順書が自動で完成します。

主な機能

  • 📸 クリック・入力・ページ遷移を自動検出してスクショ撮影
  • ✏️ 「検索ボタンをクリックします」など説明文を自動生成
  • 🎯 クリック位置を枠や矢印で強調
  • 📤 HTML / Markdown / PDF でエクスポート

特徴

  • 完全ローカル動作: スクショや操作データは外部に送信されません
  • 日本語ネイティブ対応: 説明文が自然な日本語で生成されます
  • $9/月: 競合(Scribe $23、Tango $20)より安い

技術スタック

Chrome Extension (Manifest V3)
├── React 18
├── TypeScript
├── Vite + CRXJS
├── Tailwind CSS
└── IndexedDB (idb-keyval)

サーバーレスで、すべての処理がブラウザ内で完結します。

技術的に面白かったところ

1. スクショのタイミング問題

最初は「クリック後にスクショを撮る」実装にしていましたが、これだと問題が発生しました。

ユーザーがボタンをクリック
  ↓
ページが遷移
  ↓
スクショ撮影 ← この時点でクリックしたボタンはもう画面にない!

解決策として、クリック前にスクショを撮るように変更しました。

document.addEventListener('click', async (event) => {
  // 1. クリック前に即座にスクショ
  const screenshot = await captureVisibleTab();

  // 2. 要素情報を取得(まだDOMにある状態で)
  const element = event.target;
  const rect = element.getBoundingClientRect();

  // 3. ステップとして記録
  saveStep({ screenshot, rect, ... });

  // 4. クリックは通常通り実行される
}, true);

2. クリック対象の特定

ユーザーが <div> の中の <button> の中の <span> をクリックした時、イベントターゲットはどれになるか?

答えは「場合による」です。イベントバブリングにより、実際にクリックした要素より親要素がターゲットになることがあります。

そこで、意味のある要素を探索するロジックを追加しました。

function findMeaningfulElement(target: Element): Element {
  const genericTags = ['DIV', 'SPAN', 'BODY', 'SECTION'];

  // ターゲットが汎用要素なら、子要素から意味のある要素を探す
  if (genericTags.includes(target.tagName)) {
    const button = target.querySelector('button, a, input, [role="button"]');
    if (button) return button;
  }

  return target;
}

3. 説明文の自動生成

クリックした要素から「何をクリックしたか」を説明するテキストを生成します。

優先順位:

  1. aria-label 属性
  2. placeholder 属性
  3. innerText(アイコン要素を除外)
  4. タグ名からの推測(「ボタンをクリックします」)
function getElementText(element: Element): string {
  // aria-labelを優先
  const ariaLabel = element.getAttribute('aria-label');
  if (ariaLabel) return ariaLabel;

  // placeholderをチェック
  if (element instanceof HTMLInputElement && element.placeholder) {
    return element.placeholder;
  }

  // innerTextからアイコンを除外して取得
  const clone = element.cloneNode(true) as Element;
  clone.querySelectorAll('svg, [class*="icon"]').forEach(el => el.remove());
  return clone.textContent?.trim() || '';
}

ただし、これだと「open_in_new」(Material Iconのaria-label)などが混入することがあったので、除外パターンも追加しています。

4. SPAのページ遷移検出

ReactやVueなどのSPAでは、従来の beforeunload イベントが発火しません。代わりに History API を監視します。

// pushState/replaceState をラップして検出
const originalPushState = history.pushState;
history.pushState = function(...args) {
  originalPushState.apply(this, args);
  handleNavigation();
};

// popstate(ブラウザの戻る/進む)も検出
window.addEventListener('popstate', handleNavigation);

5. 撮影中のオーバーレイUI

撮影中であることをユーザーに伝えつつ、オーバーレイ自体がスクショに映り込まないようにする必要がありました。

const overlay = document.createElement('div');
overlay.setAttribute('data-procshot-ignore', 'true');
document.body.appendChild(overlay);

// スクショ撮影時にオーバーレイを一時的に非表示
async function captureScreenshot() {
  overlay.style.display = 'none';
  const screenshot = await chrome.tabs.captureVisibleTab();
  overlay.style.display = 'block';
  return screenshot;
}

苦労したところ

Manifest V3 の制約

Chrome拡張のManifest V3では、Service Workerが非アクティブ時に停止します。これにより、録画状態の管理が複雑になりました。

// Service Workerが再起動するたびに状態を復元
chrome.storage.local.get('recordingState', (result) => {
  if (result.recordingState?.isRecording) {
    // 録画を再開
    resumeRecording(result.recordingState);
  }
});

権限の最小化

Chrome Web Storeの審査では、権限の正当性が厳しくチェックされます。<all_urls> 権限を使う理由を明確に説明する必要がありました。

この拡張機能は、ユーザーが閲覧しているWebページでスクリーンショットを撮影し、クリック位置を検出するために、すべてのURLへのアクセス権限が必要です。

今後の予定

  • AI による説明文の改善(Gemini API 連携)
  • インタラクティブ再生(実際のページ上でガイド表示)
  • チーム共有機能

おわりに

個人開発で14個目のChrome拡張機能になりました。

「こういう機能がほしい」「ここがおかしい」などフィードバックいただけると嬉しいです!

手順キャプチャ(Procshot)をChrome ウェブストアで見る

S-Hub では、生産性向上のためのツールを開発しています。他の拡張機能もぜひチェックしてみてください。

作った拡張機能

🎯 生産性ツール

  • PromptStash - AIプロンプトを保存・管理(19サービス対応)
  • DataPick - Webページからデータを抽出
  • SnippetVault - コードスニペット管理
  • ReadMark - 読書位置を記憶

🧘 デジタルウェルビーイング

🛒 EC・せどり

🔧 Web便利ツール

🏠 不動産

すべての拡張機能の詳細 → S-Hub


📝 この記事は Zenn にも掲載しています → https://zenn.dev/ktg/articles/55b63d68ac2ddb

2
2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?