извлечь текст из PDF в Javascript - PullRequest
34 голосов
/ 12 октября 2009

Интересно, возможно ли получить текст внутри PDF-файла, используя только Javascript? Если да, может кто-нибудь показать мне, как?

Я знаю, что существуют серверные библиотеки java, c # и т. Д., Но я бы предпочел не использовать сервер. спасибо

Ответы [ 5 ]

58 голосов
/ 11 декабря 2013

Это древний вопрос, но, поскольку pdf.js развивался на протяжении многих лет, я хотел бы дать новый ответ. То есть это можно сделать локально, без участия какого-либо сервера или внешнего сервиса. Новый pdf.js имеет функцию: page.getTextContent (). Вы можете получить текстовое содержание от этого. Я сделал это успешно с помощью следующего кода.

  1. То, что вы получаете на каждом этапе, - это обещание. Вам нужно написать код таким образом: .then( function(){...}), чтобы перейти к следующему шагу.

    1) PDFJS.getDocument( data ).then( function(pdf) {

    2) pdf.getPage(i).then( function(page){

    3) page.getTextContent().then( function(textContent){

  2. В итоге вы получите массив строк textContent.bidiTexts[]. Вы объединяете их, чтобы получить текст 1 страницы. Координаты текстовых блоков используются для определения необходимости вставки новой строки или пробела. (Возможно, это не совсем надежно, но из моего теста все в порядке.)

  3. Входной параметр data должен представлять собой данные типа URL или ArrayBuffer. Я использовал функцию ReadAsArrayBuffer (файл) в FileReader API для получения данных.

Надеюсь, это поможет.

Примечание: По словам какого-то другого пользователя, библиотека обновилась и привела к разрыву кода. Согласно комментарию async5 ниже, вам нужно заменить textContent.bidiTexts на textContent.items.

    function Pdf2TextClass(){
     var self = this;
     this.complete = 0;

    /**
     *
     * @param data ArrayBuffer of the pdf file content
     * @param callbackPageDone To inform the progress each time
     *        when a page is finished. The callback function's input parameters are:
     *        1) number of pages done;
     *        2) total number of pages in file.
     * @param callbackAllDone The input parameter of callback function is 
     *        the result of extracted text from pdf file.
     *
     */
     this.pdfToText = function(data, callbackPageDone, callbackAllDone){
     console.assert( data  instanceof ArrayBuffer  || typeof data == 'string' );
     PDFJS.getDocument( data ).then( function(pdf) {
     var div = document.getElementById('viewer');

     var total = pdf.numPages;
     callbackPageDone( 0, total );        
     var layers = {};        
     for (i = 1; i <= total; i++){
        pdf.getPage(i).then( function(page){
        var n = page.pageNumber;
        page.getTextContent().then( function(textContent){
          if( null != textContent.bidiTexts ){
            var page_text = "";
            var last_block = null;
            for( var k = 0; k < textContent.bidiTexts.length; k++ ){
                var block = textContent.bidiTexts[k];
                if( last_block != null && last_block.str[last_block.str.length-1] != ' '){
                    if( block.x < last_block.x )
                        page_text += "\r\n"; 
                    else if ( last_block.y != block.y && ( last_block.str.match(/^(\s?[a-zA-Z])$|^(.+\s[a-zA-Z])$/) == null ))
                        page_text += ' ';
                }
                page_text += block.str;
                last_block = block;
            }

            textContent != null && console.log("page " + n + " finished."); //" content: \n" + page_text);
            layers[n] =  page_text + "\n\n";
          }
          ++ self.complete;
          callbackPageDone( self.complete, total );
          if (self.complete == total){
            window.setTimeout(function(){
              var full_text = "";
              var num_pages = Object.keys(layers).length;
              for( var j = 1; j <= num_pages; j++)
                  full_text += layers[j] ;
              callbackAllDone(full_text);
            }, 1000);              
          }
        }); // end  of page.getTextContent().then
      }); // end of page.then
    } // of for
  });
 }; // end of pdfToText()
}; // end of class
9 голосов
/ 18 марта 2015

Я не смог заставить работать пример gm2008 (внутренняя структура данных в pdf.js явно изменилась), поэтому я написал свое собственное решение на основе обещаний, которое не использует элементы DOM, выборки запросов или холст, используя обновленный pdf.js из примера на mozilla

Он ест путь к файлу для загрузки, так как я использую его с node-webkit. Вам нужно убедиться, что вы скачали и указали куда-то cmaps, и вам нужны pdf.js и pdf.worker.js, чтобы это работало.

    /**
     * Extract text from PDFs with PDF.js
     * Uses the demo pdf.js from https://mozilla.github.io/pdf.js/getting_started/
     */
    this.pdfToText = function(data) {

        PDFJS.workerSrc = 'js/vendor/pdf.worker.js';
        PDFJS.cMapUrl = 'js/vendor/pdfjs/cmaps/';
        PDFJS.cMapPacked = true;

        return PDFJS.getDocument(data).then(function(pdf) {
            var pages = [];
            for (var i = 0; i < pdf.numPages; i++) {
                pages.push(i);
            }
            return Promise.all(pages.map(function(pageNumber) {
                return pdf.getPage(pageNumber + 1).then(function(page) {
                    return page.getTextContent().then(function(textContent) {
                        return textContent.items.map(function(item) {
                            return item.str;
                        }).join(' ');
                    });
                });
            })).then(function(pages) {
                return pages.join("\r\n");
            });
        });
    }

использование:

 self.pdfToText(files[0].path).then(function(result) {
      console.log("PDF done!", result);
 })
7 голосов
/ 14 сентября 2012

Вот некоторый код JavaScript, который делает то, что вы хотите, используя Pdf.js из http://hublog.hubmed.org/archives/001948.html:

var input = document.getElementById("input");  
var processor = document.getElementById("processor");  
var output = document.getElementById("output");  

// listen for messages from the processor  
window.addEventListener("message", function(event){  
  if (event.source != processor.contentWindow) return;  

  switch (event.data){  
    // "ready" = the processor is ready, so fetch the PDF file  
    case "ready":  
      var xhr = new XMLHttpRequest;  
      xhr.open('GET', input.getAttribute("src"), true);  
      xhr.responseType = "arraybuffer";  
      xhr.onload = function(event) {  
        processor.contentWindow.postMessage(this.response, "*");  
      };  
      xhr.send();  
    break;  

    // anything else = the processor has returned the text of the PDF  
    default:  
      output.textContent = event.data.replace(/\s+/g, " ");  
    break;  
  }  
}, true);

... и вот пример:

http://git.macropus.org/2011/11/pdftotext/example/

0 голосов
/ 27 апреля 2016

Для всех людей, которые действительно хотят использовать его на сервере узла:

/**
 * Created by velten on 25.04.16.
 */
"use strict";
let pdfUrl = "http://example.com/example.pdf";
let request = require('request');
var pdfParser = require('pdf2json');

let pdfPipe = request({url: pdfUrl, encoding:null}).pipe(pdfParser);

pdfPipe.on("pdfParser_dataError", err => console.error(err) );
pdfPipe.on("pdfParser_dataReady", pdf => {
    //optionally:
    //let pdf = pdfParser.getMergedTextBlocksIfNeeded();

    let count1 = 0;
    //get text on a particular page
    for (let page of pdf.formImage.Pages) {
        count1 += page.Texts.length;
    }

    console.log(count1);
    pdfParser.destroy();
});
0 голосов
/ 12 октября 2009

Возможно, но:

  • вам все равно придется использовать сервер, вы не сможете получить содержимое файла на компьютере пользователя, не перенеся его на сервер и обратно
  • Я не думаю, что кто-то еще написал такую ​​библиотеку

Так что, если у вас есть немного свободного времени, вы можете самостоятельно изучить формат pdf и написать такую ​​библиотеку, или вы можете просто использовать библиотеку на стороне сервера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...