歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

使用 JavaScript 實現對 PDF 的全文索引

我曾今在一個售賣法律和財務數據庫訪問方案(他們稱之為“智能信息”)的公司工作。大多數法庭記錄都是通過PACER以PDF形式提供的,一個站點被特地開發出來用於發布法庭記錄。基於這個數據集的一個意義重大的數據庫產品需要建立一條處理管道,它能夠從超過兩億分份PDF文檔中提取文本並對其進行索引,展示美國超過20年的訴訟記錄。這些處理過程將花費數月的機器時間,使得軟件工作組在構建它們時的面臨很大的壓力。在這一處理過程中的早期有個一步驟是從電子文檔化的PDF中提取出內容,其在稍後的將會被送入一個NLP處理階段——顯示關鍵字,標注部分詞類,識別實體,而然後發出報告(如果你對此感興趣,可以檢索 Python中的自然語言處理 作為入門 - 再讀一讀 這裡我的評論 )

Mozilla實驗室最近已經收到了許多為一個項目做出的嘗試,這一項目的野心令人印象深刻:在一個浏覽器中僅僅使用Javascript來對PDF進行渲染。PDF文檔的結構令人難以置信的復雜,因此要祝pdf.js工作組的兄弟們好運了!在另外一條不同的嘗試道路上,Oliver Nightingale使用Javascript實現了一個的Javascript全文索引裝置——將這兩個項目結合起來,就可以在web浏覽器中完全再現PDF處理管道。

站在一名新手的角度來看,全文索引能用戶可以搜索非結構化的文檔,也可以依據由詞頻決定的相關度分值來對結果文檔進行排名。索引裝置會計算每一個份文檔中每一個詞出現的次數,並且對文本進行最輕微的修改,以移除內容中跟搜索無關的一些文本語法特性。例如,它可能會提取出“-ing”,將元音部分變更為一般的表示形式。如果一個詞語頻繁出現在整個文檔集中,索引裝置會自動將其識別為不那麼重要的關鍵詞,而它對排名結果的影響將會被最小化。這同Google PageRank背後的基本概念是不同的,後者是基於一個引征圖來提升文檔排名的。

大多數數據庫軟件都提供了對全文索引的支持,但如果是大規模安裝的話,通常會使用功能更加強大的工具來進行處理。開源產品中主要是Solr/Lucene,Solr是圍繞Lucene庫封裝的一個web應用。它們都是用Java編寫的。

構造一個Javascript全文索引裝置使得搜索在諸如Phonegap引用,終端用戶機或者加密存儲的用戶數據這些之前很難實現搜索功能的地方成為可能。有一整個領域只研究加密的搜索指數,而在客戶機上對數據進行索引和加密看上去像是圍繞這個天生具有挑戰性的問題想出的一個好辦法。

為了測試這個處理管道,我們首先來看看如何從PDF中提取文本,這些文本將在稍後被插入到一個全文索引中。pdf.js的代碼是很有啟發性的,其中Mozilla的開發者們使用了一些並不常用的浏覽器特性,舉個例子,Web工作者,會要你設置後台的處理線程。

pdf.js 的 API大量使用約定來持有代碼中未完成操作的引用。你會使用回調來對它們進行操作:

var pdf = PDFJS.getDocument('http://www.pacer.gov/documents/pacermanual.pdf');
 
var pdf = PDFJS.getDocument('pacermanual.pdf');
pdf.then(function(pdf) {
 // this code is called once the PDF is ready
});

這樣的API看起還不怎麼成熟——理想情況下你應該能夠寫出 promise.then(f(x)).then(g(x)).then(h(x)) 等等代碼,但現在那還是不可用的。

約定模式在渲染PDF方面起了很大的作用,因為它為並行的渲染處理留下了空間。對於只是從一份PDF中提取出文本感覺上好像有大量的工作要做——你必須相信你的回調會按照秩序運行並且跟蹤到哪個是在最後。

下面的示例代碼演示了提取PDF內容,並在浏覽器中控制台日志中輸出:

‘use strict’;
var pdf = PDFJS.getDocument('http://www.pacer.gov/documents/pacermanual.pdf');
 
var pdf = PDFJS.getDocument('pacermanual.pdf');
pdf.then(function(pdf) {
 var maxPages = pdf.pdfInfo.numPages;
 for (var j = 1; j <= maxPages; j++) {
    var page = pdf.getPage(j);
 
    // the callback function - we create one per page
    var processPageText = function processPageText(pageIndex) {
      return function(pageData, content) {
        return function(text) {
          // bidiTexts has a property identifying whether this
          // text is left-to-right or right-to-left
          for (var i = 0; i < text.bidiTexts.length; i++) {
            str += text.bidiTexts[i].str;
          }
 
          if (pageData.pageInfo.pageIndex ===
              maxPages - 1) {
            // later this will insert into an index
            console.log(str);
          }
        }
      }
    }(j);
 
    var processPage = function processPage(pageData) {
      var content = pageData.getTextContent();
 
      content.then(processPageText(pageData, content));
    }
 
    page.then(processPage);
 }
});

這並不會識別頁眉和圖片.如何識別這些內容需要使用渲染代碼,需要非常理解PDF命令(PDF可能使用流渲染命令,類似於RTF)

Lunr

創建一個Lunr函數直接添加字段-所有的API都使用JSON類型,以下是一個簡單的AIP示例

doc1 = {
    id: 1,
    title: 'Foo',
    body: 'Foo foo foo!'
  };
 
doc2 = {
    id: 2,
    title: 'Bar',
    body: 'Bar bar bar!'
  }
 
doc3 = {
    id: 3,
    title: 'gary',
    body: 'Foo Bar bar bar!'
  }
 
index = lunr(function () {
    this.field('title', {boost: 10})
    this.field('body')
    this.ref('id')
  })
 
// Add documents to the index
index.add(doc1)
index.add(doc2)
index.add(doc3)

更多詳情請繼續閱讀第2頁的內容:http://www.linuxidc.com/Linux/2013-10/91375p2.htm

Copyright © Linux教程網 All Rights Reserved