2026年05月31日
複数のPDFから複数の文字列を横断検索するアプリをCodexで作成
複数のPDFに対して複数の検索語句を横断検索するWebアプリを作成してみました。
OpenAIが提供するAIコーディングエージェント「Codex」を試してみたところ、ほとんどコードを書かずに数時間でアプリを作成できました。

使い方
アプリの実行にはGitとNode.jsが必要です。
Gitでリポジトリをクローンし、依存パッケージをインストールしたうえでローカルサーバを起動します。
# 1. リポジトリをクローン
git clone git@github.com:cieloazul310/pdf-search.git
# 2. ディレクトリへ移動
cd pdf-search
# 3. 依存パッケージをインストール
npm ci
# 4. 起動
npm run dev
制作過程
1. GitHubに空のリポジトリを作成
まずGitHub上に空のリポジトリを作成します。
2. CodexとGitHubを連携し、作成したリポジトリを指定
CodexとGitHubアカウントを連携し、作業対象として先ほど作成したリポジトリを指定します。
3. プロンプトを投入
CodexのPlanモードで以下のようなプロンプトを投入しました。
PDFの文章内から特定の文字列を検索するシングルページのWebアプリケーションを作成したい
動作環境: ブラウザ(Webまたはローカルでサーバを立ち上げ)
フレームワーク: React + Vite
言語: TypeScript
リンター/フォーマッター: Biome
ターゲット(PDF): 配列(PDFのURL)
検索する文字列: 配列(LocalStorageに保存)
4. Codexが作成したPull Requestをマージ
Codexが実装作業を行うため、完了後にPull Request(PR)を作成し、それをGitHub上でマージします。
この時点で生成されたVite + Reactアプリは、ブラウザのみで完結するクライアントサイドアプリケーションでした。
5. ローカルで動作確認
ローカル環境でリポジトリをクローンし、最新のmainブランチを取得して動作確認を行いました。
すると Failed to fetch エラーが発生しました。
6. 修正依頼 → PR作成 → マージを繰り返す
調査したところ、ブラウザから外部サイト上のPDFを直接取得する際にCORS(Cross-Origin Resource Sharing)の制約へ抵触している可能性が高いことが分かりました。
そこでブラウザから直接PDFを取得する方式をやめ、ローカルサーバを経由してPDFを取得・解析する構成へ変更することにしました。もちろん実装はCodexに任せます。
1. Appの修正
CORSの問題を避けるために、PDFを/tmpまたは/.cacheなどに保存し、検索したい。
ローカルでサーバを立て、サーバからの応答を受ける形のAppとしたい。
クライアント側は、PDFと検索する文字列を入力
サーバ側では、PDFファイルをローカルに一時保存し、文字列の検索を実行し、レスポンスを返す
クライアント側で、レスポンスを表示する
2. UIの修正
現行のコードは、ターゲット(PDF)と検索する文字列は両方、テキストエリアの中に一行ずつ記載する形だが、両方ともインプット(テキスト)で入力、削除ボタンを持つリストとして表示する
---tsx
<Input>
<List>
<ListItem>
<ListText />
<RemoveButton />
</ListItem>
</List>
---
3. PDFの配列もLocalStorageに保存
PDFの配列もLocalStorageに保存する仕様にする
4. 以下のテストを導入(サーバ側)
PDF: ["https://www.kanpo.go.jp/20260519/20260519g00110/pdf/20260519g00110full00010096.pdf"]
文字列: ["浦和"]
結果がtrueになるようなテストを作成(Vitest)
前項と同様に、Codexによる実装、PR作成、マージ、ローカルでの動作確認を行いました。
サーバ経由でPDFを取得できるようにはなりましたが、PDF内の文字列検索が期待通りに動作しませんでした。この問題については後述するように、自分で修正を行いました。
その後、追加機能についてもCodexへ依頼しました。
PDFの配列、検索文字列の両方とも、ファイルアップロードで指定できる機能を搭載したい
1. UI (クライアント側)
1.1 ファイルアップロードボタンを追加する
1.2 ファイル読み込み時、PDFのURLの方は new URL などを用いて検証する
1.3 ファイル読み込み後、プレビューと追加/キャンセルの画面を表示
2. ファイルの読み込み
対応ファイル: プレーンテキスト(.txt), JSON(.json), YAML(.yml/.yaml)
2.1 プレーンテキストの場合
一行ずつ(PDFのURL/検索語句)を記載する
---txt
アントラーズ
レッドダイヤモンズ
ホーリーホック
---
2.2 JSONの場合
(PDFのURL/検索語句)を配列として記載する
---json
[
"アントラーズ",
"レッドダイヤモンズ",
"ホーリーホック"
]
---
2.3 YAMLの場合
(PDFのURL/検索語句)を配列として記載する
---yaml
- アントラーズ
- レッドダイヤモンズ
- ホーリーホック
---
同様にCodexによる実装、PR作成、マージ、ローカルでの動作確認を行いました。
こちらは概ね期待通りに動作しました。
6.1 自分で修正した箇所
前述の文字列検索が正しく動作しない問題については、コンソールログを確認しながら自力で修正しました。
原因を調べたところ、PDF.jsで日本語を含むPDFから正しくテキストを抽出するためには、環境によってはCMap(Character Map)関連のデータを適切に読み込む必要があることが分かりました。
そこで以下のように修正しました。
const loadingTask = pdfjs.getDocument({
data: pdfBytes,
+ cMapUrl: "./node_modules/pdfjs-dist/cmaps/",
+ cMapPacked: true,
});
修正後は日本語テキストの抽出が正常に行われるようになり、検索機能も期待通りに動作するようになりました。
なお、CMapはPDF内部で使用される文字コードと実際の文字を対応付けるためのマッピングデータです。特に日本語・中国語・韓国語などのPDFを扱う場合に重要になることがあります。
参考:
- 「pdf.jsを使って日本語ファイルを表示する」(Qiita)
7. 完成
最後にローカル環境で最新のmainブランチを取得し、改めて動作確認を行いました。
期待通りの動作を確認できたため、これで完成です。
ハマったポイント
Codexでは1つのタスク(チャット)を長期間使い続けるよりも、修正ごとに新しいタスクを作成した方が良いようです。
同じタスクで作業を継続すると、途中でPRをマージしても、そのタスク内では古いコミットを基準に変更を生成し続ける場合があります。その結果、新しいPRを作成した際に大量のコンフリクトが発生しました。
特に複数回のPRを経由しながら開発を進める場合は、最新のリポジトリ状態を反映した新規タスクを作成する方が安全だと感じました。
感想
ほとんどコードを書かず、それなりに整ったUIを持つアプリケーションが短時間で完成してしまったのは非常に衝撃的な体験でした。正直なところ、生成されたコードの大部分は十分に読み込めていません。
一方で、AIへ適切な指示を出すためには、使用するフレームワークやツールチェーンに関する知識が依然として重要だと感じました。
また、AI生成コードには古いAPIや非推奨の実装が含まれることもあります。そのため、ReactやViteなどの公式ドキュメントを確認しながら実装内容を検証する姿勢は今後も必要だと思います。
コードを書く量は減ったとしても、「何を作るか」「どのような技術を選定するか」「生成されたコードが正しいかを判断するか」という役割は引き続き開発者に求められると感じました。
What’s The Frequency, Kenneth? / R.E.M. (1994)
その他
その他の技術記事です。