如何使用 pdf.js 从 pdf 中正确提取文本

新手上路,请多包涵

我是 ES6 和 Promise 的新手。我正在尝试 pdf.js 将 pdf 文件的所有页面中的文本提取到字符串数组中。提取完成后,我想以某种方式解析数组。说pdf文件(通过 typedarray 正确传递)有 4 页面,我的代码是:

 let str = [];
PDFJS.getDocument(typedarray).then(function(pdf) {
  for(let i = 1; i <= pdf.numPages; i++) {
    pdf.getPage(i).then(function(page) {
      page.getTextContent().then(function(textContent) {
        for(let j = 0; j < textContent.items.length; j++) {
          str.push(textContent.items[j].str);
        }
        parse(str);
      });
    });
  }
});

它设法工作,但是,当然,问题是我的 parse 函数被调用 4 次。我只想在所有 4 页提取完成后调用 parse

原文由 Sangbok Lee 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 3.6k
2 个回答

类似于 https://stackoverflow.com/a/40494019/1765767—— 使用 Promise.all 收集页面承诺并且不要忘记链接然后是:

 function gettext(pdfUrl){
  var pdf = pdfjsLib.getDocument(pdfUrl);
  return pdf.then(function(pdf) { // get all pages text
    var maxPages = pdf.pdfInfo.numPages;
    var countPromises = []; // collecting all page promises
    for (var j = 1; j <= maxPages; j++) {
      var page = pdf.getPage(j);

      var txt = "";
      countPromises.push(page.then(function(page) { // add page promise
        var textContent = page.getTextContent();
        return textContent.then(function(text){ // return content promise
          return text.items.map(function (s) { return s.str; }).join(''); // value page text
        });
      }));
    }
    // Wait for all pages and join text
    return Promise.all(countPromises).then(function (texts) {
      return texts.join('');
    });
  });
}

// waiting on gettext to finish completion, or error
gettext("https://cdn.mozilla.net/pdfjs/tracemonkey.pdf").then(function (text) {
  alert('parse ' + text);
},
function (reason) {
  console.error(reason);
});
 <script src="https://npmcdn.com/pdfjs-dist/build/pdf.js"></script>

原文由 async5 发布,翻译遵循 CC BY-SA 4.0 许可协议

@async5 的更简洁版本,并根据最新版本更新了 "pdfjs-dist": "^2.0.943"

 import PDFJS from "pdfjs-dist";
import PDFJSWorker from "pdfjs-dist/build/pdf.worker.js"; // add this to fit 2.3.0

PDFJS.disableTextLayer = true;
PDFJS.disableWorker = true; // not availaible anymore since 2.3.0 (see imports)

const getPageText = async (pdf: Pdf, pageNo: number) => {
  const page = await pdf.getPage(pageNo);
  const tokenizedText = await page.getTextContent();
  const pageText = tokenizedText.items.map(token => token.str).join("");
  return pageText;
};

/* see example of a PDFSource below */
export const getPDFText = async (source: PDFSource): Promise<string> => {
  Object.assign(window, {pdfjsWorker: PDFJSWorker}); // added to fit 2.3.0
  const pdf: Pdf = await PDFJS.getDocument(source).promise;
  const maxPages = pdf.numPages;
  const pageTextPromises = [];
  for (let pageNo = 1; pageNo <= maxPages; pageNo += 1) {
    pageTextPromises.push(getPageText(pdf, pageNo));
  }
  const pageTexts = await Promise.all(pageTextPromises);
  return pageTexts.join(" ");
};

这是对应的打字稿声明文件,如果有人需要的话,我会使用它。

 declare module "pdfjs-dist";

type TokenText = {
  str: string;
};

type PageText = {
  items: TokenText[];
};

type PdfPage = {
  getTextContent: () => Promise<PageText>;
};

type Pdf = {
  numPages: number;
  getPage: (pageNo: number) => Promise<PdfPage>;
};

type PDFSource = Buffer | string;

declare module 'pdfjs-dist/build/pdf.worker.js'; // needed in 2.3.0

如何从带缓冲区的文件(从节点类型)获取 PDFSource 的示例:

 file.arrayBuffer().then((ab: ArrayBuffer) => {
  const pdfSource: PDFSource = Buffer.from(ab);
});

原文由 Atul 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题