Al tratar con archivos de formato de documento portátil (PDF), el usuario puede querer extraer todo el texto de un archivo PDF. Por lo tanto, el usuario no tiene que seleccionar todo el texto de un PDF con el mouse y luego hacer algo con él.
En este artículo aprenderá a extraer el texto de un PDF con Javascript usando pdf.js. Esta biblioteca es una plataforma basada en estándares web de uso general para analizar y representar archivos PDF. Este proyecto usa diferentes capas , vamos a usar específicamente 2, la capa de núcleo y la de visualización. PDF.js depende en gran medida del uso de Promises. Si las promesas son nuevas para usted, se recomienda que se familiarice con ellas antes de continuar . PDF.js está impulsado por la comunidad y es compatible con Mozilla Labs.
Habiendo dicho eso, ¡comencemos!
Requisitos
- Disponibilidad de WebWorkers en el navegador ( ver tabla de compatibilidad ).
- La API de Promises se usa con frecuencia en casi todos los métodos de pdf.js ( puede usar un polyfill para brindar soporte para navegadores desactualizados ).
- Obviamente, una copia de pdf.js ( descárguela del sitio web aquí ).
Para obtener más información sobre pdf.js, visite el repositorio oficial de Github aquí .
1. Incluya los archivos necesarios
Para extraer el texto de un PDF , necesitará al menos 3 archivos (2 de ellos cargados de forma asincrónica) . Como se mencionó anteriormente, vamos a usar pdf.js
. El precompilado de esta biblioteca se basa en 2 archivos a saber pdf.js
y pdf.worker.js
. El pdf.js
archivo debe incluirse mediante una etiqueta de secuencia de comandos:
<script src="/path/to/pdf.js"></script>
Y pdf.worker.js
debe cargarse a través del workerSrc
método, que espera la URL y la carga automáticamente. Debe almacenar la URL del PDF que desea convertir en una variable que se utilizará más adelante:
<script>
// Ruta al archivo PDF
var PDF_URL = '/path/to/example.pdf';
// Especificar la ruta al worker
PDFJS.workerSrc = '/path/to/pdf.worker.js';
</script>
Con los scripts requeridos, puede proceder a extraer el texto de un PDF siguiendo los siguientes pasos.
2. Cargar PDF
Proceda a importar el PDF que desea convertir en texto usando el getDocument
método de PDFJS
(expuesto globalmente una vez que el script pdf.js se carga en el documento). La estructura del objeto de PDF.js sigue vagamente la estructura de un PDF real. En el nivel superior hay un objeto de documento. Desde el documento, se puede obtener más información y páginas individuales. Utilice el siguiente código para obtener el documento PDF:
Nota
Para evitar problemas de CORS, el PDF debe entregarse desde el mismo dominio del documento web (por ejemplo, www.yourdomain.com/pdf-to-test.html y www.yourdomain.com/pdffile.pdf). Además, puede cargar el documento PDF a través de base64 directamente en el documento sin realizar ninguna solicitud (lea los documentos).
var PDF_URL = '/path/to/example.pdf';
PDFJS.getDocument(PDF_URL).then(function (PDFDocumentInstance) {
// Utilice PDFDocumentInstance para extraer el texto más tarde
}, function (reason) {
// Error de carga de PDF
console.error(reason);
});
El PDFDocumentInstance
es un objeto que contiene métodos útiles que vamos a utilizar para extraer el texto del PDF.
3. Extraer texto de una sola página
El PDFDocumentInstance
objeto recuperado incluso del getDocument
método (paso anterior) le permite explorar el PDF a través de un método útil, a saber getPage
. Este método espera como primer argumento el número de página del PDF que se debe procesar, luego devuelve (cuando se cumple la promesa) como variable el pdfPage
. Desde el pdfPage
, para lograr nuestro objetivo de extraer el texto de un PDF, vamos a confiar en el getTextContent
método. El getTextContent
método de una página pdf es un método basado en promesas que devuelve un objeto con 2 propiedades:
items
: Matriz [X]styles
: Objeto
Estamos interesados ââen los objetos almacenados en la matriz de elementos. Esta matriz contiene varios objetos (o solo uno según el contenido del PDF) que tienen la siguiente estructura:
{
"dir":"ltr",
"fontName": "g_d0_f2",
"height": 8.9664,
"width": "227.1458",
"str": "When a trace call returns blabla bla ..."
}
¿Ves algo de interés? Así es ! el objeto contiene una str
propiedad que tiene el texto que debe dibujarse en el PDF. Para obtener todo el texto de la página solo necesitas concatenar todas las str
propiedades de todos los objetos. Eso es lo que hace el siguiente método, un método simple basado en promesas que devuelve el texto concatenado de la página cuando se resuelve:
Nota importante contra el odio
Antes de comenzar en los comentarios para decir que en lugar de concatenar cadenas, se +=
debe evitar el uso y, en su lugar, hacer algo como almacenar las cadenas dentro de una matriz y luego unirlas, debe saber que, según los puntos de referencia en JSPerf, el uso +=
es el método más rápido, aunque no necesariamente en todos los navegadores. Lea más sobre esto aquí, y en caso de que no le guste, modifíquelo como desee.
/**
* Recupera el texto de una página específica dentro de un documento PDF obtenido a través de pdf.js
*
* @param {Integer} pageNum Specifies the number of the page
* @param {PDFDocument} PDFDocumentInstance The PDF document obtained
**/
function getPageText(pageNum, PDFDocumentInstance) {
// Devuelve una promesa que se resuelve una vez que se recupera el texto de la página
return new Promise(function (resolve, reject) {
PDFDocumentInstance.getPage(pageNum).then(function (pdfPage) {
// El truco principal para obtener el texto de la página PDF es utilizar el método getTextContent
pdfPage.getTextContent().then(function (textContent) {
var textItems = textContent.items;
var finalString = "";
// Concatenar la cadena del elemento a la cadena final
for (var i = 0; i < textItems.length; i++) {
var item = textItems[i];
finalString += item.str + " ";
}
// Resuelve la promesa con el texto recuperado incluso de la página
resolve(finalString);
});
});
});
}
Bastante simple, ¿no? Ahora solo necesitas escribir el código descrito anteriormente:
var PDF_URL = '/path/to/example.pdf';
PDFJS.getDocument(PDF_URL).then(function (PDFDocumentInstance) {
var totalPages = PDFDocumentInstance.numPages;
var pageNumber = 1;
// Extrae el texto
getPageText(pageNumber , PDFDocumentInstance).then(function(textPage){
// Mostrar el texto de la página en la consola
console.log(textPage);
});
}, function (reason) {
// Error de carga de PDF
console.error(reason);
});
Y el texto (si hay alguno) de la primera página del PDF debería mostrarse en la consola. Increíble !
4. Extraer texto de varias páginas
Para extraer el texto de muchas páginas simultáneamente, usaremos el mismo getPageText
método creado en el paso anterior que devuelve una promesa cuando se extrae el contenido de una página. Como la asincronía podría dar lugar a malentendidos muy problemáticos, y para recuperar el texto correctamente, vamos a activar múltiples promesas a la vez, lo Promise.all
que le permite resolver múltiples promesas a la vez en el mismo orden en que se proporcionaron como argumento ayudar a controlar el problema de las promesas que se ejecutan primero que otras) y recuperar respectivamente los resultados en una matriz con el mismo orden:
var PDF_URL = '/path/to/example.pdf';
PDFJS.getDocument(PDF_URL).then(function (PDFDocumentInstance) {
var pdfDocument = pdf;
// Crea una matriz que contendrá nuestras promesas
var pagesPromises = [];
for (var i = 0; i < pdf.numPages; i++) {
// Requerido para evitar que i sea siempre el total de páginas
(function (pageNumber) {
// Almacene la promesa de getPageText que devuelve el texto de una página
pagesPromises.push(getPageText(pageNumber, pdfDocument));
})(i + 1);
}
// Ejecuta todas las promesas
Promise.all(pagesPromises).then(function (pagesText) {
// Mostrar texto de todas las páginas de la consola
// e.g ["Text content page 1", "Text content page 2", "Text content page 3" ... ]
console.log(pagesText);
});
}, function (reason) {
// Error de carga de PDF
console.error(reason);
});
Ejemplo en vivo
Juega con el siguiente fiddle, extrae el contenido de todas las páginas de este PDF y las agrega como texto al DOM (ve a la pestaña Resultado):
Ejemplo
El siguiente documento contiene un ejemplo muy simple que mostrará el contenido de cada página de un PDF en la consola. Solo necesita implementarlo en un servidor http, agregar pdf.js y pdf.worker.js, un PDF para probar y listo:
<!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="/path/to/pdf.js"></script>
<script>
var urlPDF = '/path/to/example.pdf';
PDFJS.workerSrc = '/path/to/pdf.worker.js';
PDFJS.getDocument(urlPDF).then(function (pdf) {
var pdfDocument = pdf;
var pagesPromises = [];
for (var i = 0; i < pdf.numPages; i++) {
// Requerido para evitar que i sea siempre el total de páginas
(function (pageNumber) {
pagesPromises.push(getPageText(pageNumber, pdfDocument));
})(i + 1);
}
Promise.all(pagesPromises).then(function (pagesText) {
// Mostrar texto de todas las páginas de la consola
console.log(pagesText);
});
}, function (reason) {
// Error de carga de PDF
console.error(reason);
});
/**
* Recupera el texto de una página específica dentro de un documento PDF obtenido a través de pdf.js
*
* @param {Integer} pageNum Especifica el número de la página
* @param {PDFDocument} PDFDocumentInstance El documento PDF obtenido
**/
function getPageText(pageNum, PDFDocumentInstance) {
// Devuelve una promesa que se resuelve una vez que se recupera el texto de la página
return new Promise(function (resolve, reject) {
PDFDocumentInstance.getPage(pageNum).then(function (pdfPage) {
// El truco principal para obtener el texto de la página PDF es utilizar el método getTextContent
pdfPage.getTextContent().then(function (textContent) {
var textItems = textContent.items;
var finalString = "";
// Concatenar la cadena del elemento a la cadena final
for (var i = 0; i < textItems.length; i++) {
var item = textItems[i];
finalString += item.str + " ";
}
// Resuelva la promesa con el texto recuperado incluso de la página
resolve(finalString);
});
});
});
}
</script>
</body>
</html>
Si no se está obteniendo el texto
Si ya probaste el código y no se está obteniendo ningún tipo de texto, es porque probablemente tu pdf no lo tenga . Probablemente el texto PDF que no puede ver no es texto sino una imagen, entonces el proceso explicado en este proceso no le ayudará. Puede utilizar otros enfoques como el Reconocimiento óptico de caracteres (OCR), sin embargo, no se recomienda hacerlo en el lado del cliente sino en el lado del servidor (consulte el uso de Node.js de OCR o con PHP en Symfony ).
Que te diviertas ❤️!
Conviertete en un programador más sociable