Aprende a extraer el texto de un PDF con JavaScript usando pdf.js

Cómo convertir PDF a texto (extraer texto de PDF) con JavaScript

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

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.jspdf.worker.js. El pdf.jsarchivo debe incluirse mediante una etiqueta de secuencia de comandos:

<script src="/path/to/pdf.js"></script>

pdf.worker.js debe cargarse a través del  workerSrcmé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 getDocumentmé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 PDFDocumentInstancees 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 PDFDocumentInstanceobjeto recuperado incluso del getDocumentmé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  getTextContentmétodo. El getTextContentmé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 strpropiedad que tiene el texto que debe dibujarse en el PDF. Para obtener todo el texto de la página solo necesitas concatenar todas las strpropiedades 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  getPageTextmé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.allque 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 ❤️!


Interesado en la programación desde los 14 años, Carlos es un programador autodidacta, fundador y autor de la mayoría de los artículos de Our Code World.

Conviertete en un programador más sociable

Patrocinadores