本文概述
- 要求
- 1.包含必需的文件
- 2.加载PDF
- 3.从单个页面提取文本
- 4.从多个页面提取文本
- 现场例子
- 例子
- 文本未检索
在本文中, 你将学习如何使用pdf.js从带有Javascript的PDF中提取文本。该库是基于Web标准的通用平台, 用于解析和呈现PDF。这个项目使用不同的层, 我们将专门使用2层, 即核心层和显示层。 PDF.js在很大程度上依赖于Promises的使用。如果对你而言是新的承诺, 建议你在继续之前先熟悉它们。 PDF.js由社区驱动, 并由Mozilla Labs支持。
话虽如此, 让我们开始吧!
要求
- WebWorkers在浏览器中的可用性(请参阅兼容性表)。
- Promises API在pdf.js的几乎所有方法中都经常使用(你可以使用polyfill为过时的浏览器提供支持)。
- 显然, 是pdf.js的副本(可从此处的网站下载)。
1.包含必需的文件为了从PDF中提取文本, 你至少需要3个文件(其中2个文件是异步加载的)。如前所述, 我们将使用pdf.js。该库的Prebuilt基于2个文件, 即pdf.js和pdf.worker.js。 pdf.js文件应通过脚本标记包括在内:
<
script src="http://www.srcmini.com/path/to/pdf.js">
<
/script>
pdf.worker.js应该通过workerSrc方法加载, 该方法需要URL并自动加载。你需要将要转换的PDF的URL存储在一个变量中, 该变量将在以后使用:
<
script>
// Path to PDF filevar PDF_URL = '/path/to/example.pdf';
// Specify the path to the workerPDFJS.workerSrc = 'http://www.srcmini.com/path/to/pdf.worker.js';
<
/script>
使用所需的脚本, 你可以按照以下步骤继续提取PDF文本。
2.加载PDF继续使用PDFJS的getDocument方法导入要转换为文本的PDF(在pdf.js脚本加载到文档中后全局公开)。 PDF.js的对象结构大致遵循实际PDF的结构。在顶层有一个文档对象。从文档中可以获取更多信息和各个页面。使用以下代码获取PDF文档:
注意为避免发生CORS问题, 需要从网络文档的同一域中提供PDF(例如, www.yourdomain.com / pdf-to-test.html和www.yourdomain.com/pdffile.pdf)。此外, 你可以直接通过base64将PDF文档加载到文档中, 而无需发出任何请求(请阅读文档)。
var PDF_URL= '/path/to/example.pdf';
PDFJS.getDocument(PDF_URL).then(function (PDFDocumentInstance) {// Use the PDFDocumentInstance To extract the text later}, function (reason) {// PDF loading errorconsole.error(reason);
});
PDFDocumentInstance是一个对象, 其中包含有用的方法, 我们将使用这些方法从PDF中提取文本。
3.从单个页面提取文本从getDocument方法检索的PDFDocumentInstance对象(上一步)使你可以通过一种有用的方法getPage浏览PDF。此方法期望将要处理的PDF页数作为第一个参数, 然后将其(在实现诺言时)作为pdfPage变量返回。从pdfPage, 要实现我们从PDF提取文本的目标, 我们将依赖于getTextContent方法。 pdf页面的getTextContent方法是基于promise的方法, 该方法返回具有2个属性的对象:
- 项目:数组[X]
- 样式:物件
{"dir":"ltr", "fontName": "g_d0_f2", "height": 8.9664, "width": "227.1458", "str": "When a trace call returns blabla bla ..."}
你看到有趣的东西了吗?那就对了 !该对象包含一个str属性, 该属性具有应绘制到PDF中的文本。要获取页面的所有文本, 你只需要串联所有对象的所有str属性。这就是以下方法的作用, 这是一个简单的基于promise的方法, 该方法在解决时返回页面的串联文本:
重要的反仇恨说明在开始发表评论之前, 应该避免使用+ =连接字符串, 而要做类似将字符串存储在数组中然后将它们联接的操作, 基于JSPerf的基准, 你应该知道使用+ =是最快的方法, 尽管不一定在每个浏览器中都可以。在这里阅读有关它的更多信息, 如果你不喜欢它, 请根据需要进行修改。
/** * Retrieves the text of a specif page within a PDF Document obtained through pdf.js * * @param {Integer} pageNum Specifies the number of the page * @param {PDFDocument} PDFDocumentInstance The PDF document obtained **/function getPageText(pageNum, PDFDocumentInstance) {// Return a Promise that is solved once the text of the page is retrievenreturn new Promise(function (resolve, reject) {PDFDocumentInstance.getPage(pageNum).then(function (pdfPage) {// The main trick to obtain the text of the PDF page, use the getTextContent methodpdfPage.getTextContent().then(function (textContent) {var textItems = textContent.items;
var finalString = "";
// Concatenate the string of the item to the final stringfor (var i = 0;
i <
textItems.length;
i++) {var item = textItems[i];
finalString += item.str + " ";
}// Solve promise with the text retrieven from the pageresolve(finalString);
});
});
});
}
很简单不是吗?现在, 你只需要编写前面描述的代码:
var PDF_URL= '/path/to/example.pdf';
PDFJS.getDocument(PDF_URL).then(function (PDFDocumentInstance) {var totalPages = PDFDocumentInstance.numPages;
var pageNumber = 1;
// Extract the textgetPageText(pageNumber , PDFDocumentInstance).then(function(textPage){// Show the text of the page in the consoleconsole.log(textPage);
});
}, function (reason) {// PDF loading errorconsole.error(reason);
});
PDF第一页的文本(如果有的话)应显示在控制台中。太棒了!
4.从多个页面提取文本为了同时提取多个页面的文本, 我们将使用在上一步中创建的相同的getPageText方法, 该方法在提取页面内容时返回一个promise。由于异步可能导致非常严重的误解, 并且为了正确检索文本, 我们将使用Promise一次触发多个promise.all允许你按提供它们作为参数的顺序来同时解决多个promise (这将有助于控制先执行的Promise问题), 并分别以相同的顺序在数组中检索结果:
var PDF_URL = '/path/to/example.pdf';
PDFJS.getDocument(PDF_URL).then(function (PDFDocumentInstance) {var pdfDocument = pdf;
// Create an array that will contain our promises var pagesPromises = [];
for (var i = 0;
i <
pdf.numPages;
i++) {// Required to prevent that i is always the total of pages(function (pageNumber) {// Store the promise of getPageText that returns the text of a pagepagesPromises.push(getPageText(pageNumber, pdfDocument));
})(i + 1);
}// Execute all the promisesPromise.all(pagesPromises).then(function (pagesText) {// Display text of all the pages in the console// e.g ["Text content page 1", "Text content page 2", "Text content page 3" ... ]console.log(pagesText);
});
}, function (reason) {// PDF loading errorconsole.error(reason);
});
现场例子播放以下小提琴, 它将提取此PDF所有页面的内容, 并将它们作为文本附加到DOM(转到” 结果” 选项卡):
例子以下文档包含一个非常简单的示例, 该示例将在控制台中显示PDF每页的内容。你只需要在http服务器上实现它, 添加pdf.js和pdf.worker.js, 一个要测试的PDF就是这样:
<
!DOCTYPE html>
<
html lang="en">
<
head>
<
title>
<
/title>
<
meta charset="UTF-8">
<
meta name="viewport" content="width=device-width, initial-scale=1">
<
/head>
<
body>
<
h1>
PDF.js<
/h1>
<
script src="http://www.srcmini.com/path/to/pdf.js">
<
/script>
<
script>
var urlPDF = '/path/to/example.pdf';
PDFJS.workerSrc = 'http://www.srcmini.com/path/to/pdf.worker.js';
PDFJS.getDocument(urlPDF).then(function (pdf) {var pdfDocument = pdf;
var pagesPromises = [];
for (var i = 0;
i <
pdf.numPages;
i++) {// Required to prevent that i is always the total of pages(function (pageNumber) {pagesPromises.push(getPageText(pageNumber, pdfDocument));
})(i + 1);
}Promise.all(pagesPromises).then(function (pagesText) {// Display text of all the pages in the consoleconsole.log(pagesText);
});
}, function (reason) {// PDF loading errorconsole.error(reason);
});
/*** Retrieves the text of a specif page within a PDF Document obtained through pdf.js * * @param {Integer} pageNum Specifies the number of the page * @param {PDFDocument} PDFDocumentInstance The PDF document obtained **/function getPageText(pageNum, PDFDocumentInstance) {// Return a Promise that is solved once the text of the page is retrievenreturn new Promise(function (resolve, reject) {PDFDocumentInstance.getPage(pageNum).then(function (pdfPage) {// The main trick to obtain the text of the PDF page, use the getTextContent methodpdfPage.getTextContent().then(function (textContent) {var textItems = textContent.items;
var finalString = "";
// Concatenate the string of the item to the final stringfor (var i = 0;
i <
textItems.length;
i++) {var item = textItems[i];
finalString += item.str + " ";
}// Solve promise with the text retrieven from the pageresolve(finalString);
});
});
});
}<
/script>
<
/body>
<
/html>
文本未检索如果你已经尝试过该代码, 但没有获得任何文本, 那是因为你的pdf可能没有任何文本。你可能看不到的PDF文本不是文本而是图像, 因此此过程中说明的过程将无济于事。你可以使用其他方法, 例如光学字符识别(OCR), 但是不建议在客户端而是在服务器端进行此操作(请参阅OCR的Node.js用法或Symfony中的PHP)。
【如何使用JavaScript将PDF转换为文本(从PDF提取文本)】编码愉快!
推荐阅读
- 如何使用浏览器中的JavaScript从剪贴板检索图像
- 使用浏览器工具或创建自己的基准来使用JavaScript衡量功能的性能
- 如何在浏览器中使用JavaScript创建Gameboy Advance Emulator(GBA)
- Linux(内核剖析):09---进程调度之Linux调度的实现(struct sched_entityschedule())
- Linux(内核剖析):08---进程调度之Linux调度算法(调度器类公平调度(CFS))
- helm v3 在k8s 上面的部署skywalking
- 服务/软件管理(19---Linux与Windows之间Zmodem协议的开启与使用(rzsz命令))
- Linux(内核剖析):06---进程之线程的实现
- 服务/软件管理(17---Linux与Windows之间Samba服务的开启与使用)