当前位置:  开发笔记 > 编程语言 > 正文

在Javascript中从pdf中提取文本

如何解决《在Javascript中从pdf中提取文本》经验,为你挑选了3个好方法。

我想知道是否可以通过仅使用Javascript获取PDF文件中的文本?如果有,任何人都可以告诉我如何?

我知道有一些服务器端的java,c#等库,但我不想使用服务器.谢谢



1> gm2008..:

这是一个古老的问题,但由于pdf.js多年来一直在发展,我想给出一个新的答案.也就是说,它可以在本地完成,而不涉及任何服务器或外部服务.新的pdf.js有一个函数:page.getTextContent().您可以从中获取文本内容.我用以下代码成功完成了它.

    你在每一步中获得的是一个承诺.您需要以这种方式编码:.then( function(){...})继续下一步.

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

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

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

    你最终得到的是一个字符串数组textContent.bidiTexts[].您将它们连接起来以获取1页的文本.文本块的坐标用于判断是否需要插入换行符或空格.(这可能不是很完整,但从我的测试看来似乎没问题.)

    输入参数data必须是URL或ArrayBuffer类型数据.我在FileReaderAPI中使用了ReadAsArrayBuffer(file)函数 来获取数据.

希望这可以帮助.

注意:根据其他一些用户的说法,库已更新并导致代码中断.根据下面async5的评论,你需要替换textContent.bidiTextstextContent.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


用textContent.items替换textContent.bidiTexts
"古代问题",但答案很好.您有任何想法如何让textLayer不在各个div中渲染字符,而是将它们渲染为整个单词?我试图使用文本层重叠与divs绝对定位,因为它们有很多,所以我获得了相当大的性能.如果你更喜欢这个作为一个单独的实际StackOverflow问题,我会做一个.

2> SchizoDuckie..:

我无法让gm2008的例子工作(pdf.js上的内部数据结构明显改变了),所以我编写了自己完全基于承诺的解决方案,不使用任何DOM元素,queryselectors或canvas,使用更新的pdf来自mozilla示例的.js

它使用了一个文件路径进行上传,因为我正在使用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);
 })



3> rphv..:

这里有一些JavaScript代码可以使用http://hublog.hubmed.org/archives/001948.html中的 Pdf.js执行您想要的操作:

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/

推荐阅读
jerry613
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有