🌊

【PDF.js】ReactでPDF.jsを使ってPDFテキストを抽出したい

2024/11/26に公開

背景

業務でPDF.jsを使用してPDFテキストを抽出する機能を作成しましたので、PDF.jsのお作法や詰まったところを書き連ねていきます。

動作環境

  • React 18.3.1
  • Typescript 5.5.3
  • PDF.js 4.8.69
  • yarn 4.4.1

基本

インストール

yarn add -D pdfjs-dist

https://mozilla.github.io/pdf.js/

PDF.js ワーカーの設定

import * as pdfjsLib from "pdfjs-dist";

pdfjsLib.GlobalWorkerOptions.workerSrc = new URL(
  "pdfjs-dist/build/pdf.worker.min.mjs",
  import.meta.url,
).toString();

PDFの読み込み


const pdfData = await selectedPdf.arrayBuffer();

const loadingTask = pdfjsLib.getDocument({
    data: pdfData, // ArrayBuffer型である必要がある
    verbosity: 1,
});
  • verbosity:PDF.js のデバッグログの出力レベル。
    • 0:ログ出力を無効化(デフォルト)。エラーや警告メッセージは表示されません。
    • 1:エラーのみを表示。PDF.js の動作に影響を与える重大な問題のみがログに記録されます。
    • 2:エラーと警告を表示。PDF.js の動作に影響を与える可能性がある問題も記録されます。
    • 3:エラー、警告、情報メッセージをすべて表示。詳細なデバッグ情報が得られます(開発時向け)。

応用

PDFのページ数を取得する

const loadingTask = pdfjsLib.getDocument({
    data: pdfData, 
    verbosity: 1,
});

const pdf = await loadingTask.promise;
const maxPages = pdf.numPages;

PDFテキストを取得する

let pdfText = "";
const page = await pdf.getPage(pageNumber); // 取得したいページ数を引数に指定
const { items } = await page.getTextContent({
  includeMarkedContent: true,
});

const pageText = items
  .map((item) => {
    return "str" in item ? (item.hasEOL ? "\n" : item.str) : "";
  })
  .join("");

pdfText += pageText + "\n";
  • hasEOL(boolean):改行コードの場合、trueになる
  • str:格納している文字
    • 一文字ずつ格納されているので注意
      • 区切り文字が何なのかはわかってないです🙇

全てのページのテキストを取得する

const loadingTask = pdfjsLib.getDocument({
    data: pdfData,
    verbosity: 0,
});
const pdf = await loadingTask.promise;
const maxPages = pdf.numPages;
let pdfText = "";

// テキスト抽出
for (let pageNumber = 1; pageNumber <= maxPages; pageNumber++) {
    const page = await pdf.getPage(pageNumber);
    const { items } = await page.getTextContent({
      includeMarkedContent: true,
    });
    
    const pageText = items
      .map((item) => {
        return "str" in item ? (item.hasEOL ? "\n" : item.str) : "";
      })
      .join("");
    
    pdfText += pageText + "\n";
}

実務で詰まったところ

PDF.js ワーカーの設定

import * as pdfjs from 'pdfjs-dist/legacy/build/pdf';
import * as pdfjsWorker from 'pdfjs-dist/legacy/build/pdf.worker.entry';

pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;

ネットの記事を見ているが上記のようにワーカーを設定しているが、
実際pdfjs-dist/legacy/build/pdf.worker.entryのモジュールを読み込めない。

バージョンアップして読み込み方が変わったのかな??

Warning: TT: undefined function: 3 の解決方法

エラー表示条件:PDFテキスト内に解析できないフォントが存在する場合

なんと解決方法はない。(解決しなくていい?)
getDocumentのverbosityを0に指定すれば表示されない。
https://github.com/mozilla/pdf.js/issues/3768


参考にした記事
https://zenn.dev/ptna/articles/63df4a8007f9d3
https://zenn.dev/tenkei/scraps/6bf241e681923d

Discussion