在不依赖操作系统的情况下,使用Node.js提取PDF文本

16

有没有一种在nodejs中提取PDF文本的方法,且不需要任何操作系统依赖项(例如pdf2text或Windows上的xpdf)?我找不到任何“原生”的nodejs pdf软件包。它们总是在现有的操作系统命令之上进行封装/实用程序。

5个回答

12

经过一些工作,我终于得到了一个可靠的函数,使用https://github.com/mozilla/pdfjs-dist从PDF读取文本。

要使其工作,首先在命令行中进行npm安装:

npm i pdfjs-dist

然后创建一个具有以下代码的文件(在本例中,我将文件命名为“pdfExport.js”):

const pdfjsLib = require("pdfjs-dist");

async function GetTextFromPDF(path) {
    let doc = await pdfjsLib.getDocument(path).promise;
    let page1 = await doc.getPage(1);
    let content = await page1.getTextContent();
    let strings = content.items.map(function(item) {
        return item.str;
    });
    return strings;
}
module.exports = { GetTextFromPDF }

然后,它可以在任何其他JS文件中使用,如下所示:
const pdfExport = require('./pdfExport');
pdfExport.GetTextFromPDF('./sample.pdf').then(data => console.log(data));

1
你好 @Jack,对我来说,只有你的代码能够在nwjs应用程序中提取pdfjs中的文本。我已经尝试了一个星期。最终让它工作了。非常感谢你的答案。 - Sunil Kumar
出现以下错误:浏览器/环境不支持 PDF.js 库使用的关键功能的本机支持(例如 Path2D 和/或 ReadableStream);请改用“legacy”构建。 - Abhay
工作顺利无阻,兄弟,谢谢你。 - Vibhu Pandey

8
您有没有查看过PDF2Json?它是建立在PDF.js之上的。虽然它不能提供单行文本输出,但我相信您可以根据生成的Json输出重构最终文本:

'Texts':一个文本块数组,包括位置、实际文本和样式信息: 'x' 和 'y': 相对坐标用于定位 'clr':颜色词典中的颜色索引,与'Fill'对象中的'clr'字段相同。如果能在颜色词典中找到颜色,则将'oc'字段添加到该字段中作为“原始颜色”值。 'A':文本对齐方式,包括: left center right 'R':文本运行的数组,每个文本运行对象都有两个主要字段: 'T':实际文本 'S':来自样式词典的样式索引。有关“样式词典”的更多信息,请参见“字典参考”部分


谢谢,这似乎能完成任务。- Bart - bartium

7

如果有人在未来遇到这个问题,我想发表一下我的看法。 我曾经遇到这个问题,花了几个小时研究了NPM上的所有PDF库。我的要求是必须在AWS Lambda上运行,因此不能依赖操作系统相关性。

下面的代码修改自另一个stackoverflow答案(我目前找不到)。唯一的区别是我们导入与 Node >= 12 兼容的 ES5 版本。如果只导入pdfjs-dist,会出现"Readable Stream is not defined"的错误。希望对你有所帮助!

import * as pdfjslib from 'pdfjs-dist/es5/build/pdf.js';

export default class Pdf {
  public static async getPageText(pdf: any, pageNo: number) {
    const page = await pdf.getPage(pageNo);
    const tokenizedText = await page.getTextContent();
    const pageText = tokenizedText.items.map((token: any) => token.str).join('');
    return pageText;
  }

  public static async getPDFText(source: any): Promise<string> {
    const pdf = await pdfjslib.getDocument(source).promise;
    const maxPages = pdf.numPages;
    const pageTextPromises = [];
    for (let pageNo = 1; pageNo <= maxPages; pageNo += 1) {
      pageTextPromises.push(Pdf.getPageText(pdf, pageNo));
    }
    const pageTexts = await Promise.all(pageTextPromises);
    return pageTexts.join(' ');
  }
}

用法

const fileBuffer = fs.readFile('sample.pdf');
const pdfText = await Pdf.getPDFText(fileBuffer);

我也在尝试在 Lambda 函数中运行 pdfjs。当我导入库时,我遇到了以下错误:设置虚拟工作程序失败:“无法找到模块'./pdf.worker.js'”。你是否遇到过这个问题,并可能已经找到了解决方案? - florian norbert bepunkt
你最近几年里有没有更新过这个代码?我一直在使用这个解决方案,它还可以,但我希望能有一个和https://pdftotext.com/同样好的解决方案。 - chrismead
1
我查看了 pdtto ext.com,他们不在云端处理 PDF,看起来是使用 pdf.js 的浏览器解决方案。 - Kalana Perera

2

对于我来说,使用14.20.1版本的node和"pdf-parse": "^1.1.1"很有效。

你可以使用以下命令进行安装:

yarn add pdf-parse

这是将PDF文件转换为文本的主要函数。

const path = require('path');
const fs = require('fs');
const pdf = require('pdf-parse');
const assert = require('assert');

const extractText = async (pathStr) => {
  assert (fs.existsSync(pathStr), `Path does not exist ${pathStr}`)
  const pdfFile = path.resolve(pathStr)
  const dataBuffer = fs.readFileSync(pdfFile);
  const data = await pdf(dataBuffer)
  return data.text
}

module.exports = {
  extractText
}

那么你可以像这样使用该函数:
const { extractText } = require('../api/lighthouse/lib/pdfExtraction')

extractText('./data/CoreDeveloper-v5.1.4.pdf').then(t => console.log(t))

0

你可以直接使用PDF.js而不是使用提议的PDF2Json(https://github.com/mozilla/pdfjs-dist)。这样做的好处是你不依赖于拥有PDF2Json和更新PDF.js基础的人的谦虚。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接