実現したいこと
掲題の通り、PDFのテキストをJavaScriptを利用して抽出したいと考えております。そこで利用可能なものとして、pdf.js-extractに見つけ、興味を持ち利用したいと考えております。
前提
- ここでいうJavaScriptはクライアント・ブラウザで動作させることができるものとして考えております。
- 当方npm等のパッケージ管理には不案内ではありますが、それ自体の導入は無事完了
npm --ver 10.2.3
しており、pdf.js-extractにある指示に従い、npm i pdf.js-extract
によりローカルインストールを完了しております。
発生している問題・エラーメッセージ
上記の準備を終え、Example Usageにある通り、以下のコードをindex.htmlで実行いたしました。
HTML
1<!--index.html--> 2<!DOCTYPE html> 3<html lang="ja"> 4 5<head> 6 <meta charset="UTF-8"> 7 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 8 <title>Document</title> 9 10</head> 11 12<body> 13 14 <script> 15 const PDFExtract = require('pdf.js-extract').PDFExtract; 16 const pdfExtract = new PDFExtract(); 17 const options = {}; /* see below */ 18 pdfExtract.extract('test.pdf', options, (err, data) => { 19 if (err) return console.log(err); 20 console.log(data); 21 }); 22 </script> 23</body> 24</html>
するとブラウザのDevelper Tool上以下のようなメッセージが出力されました。
Uncaught ReferenceError: require is not defined
試したこと
この原因が調べてみるとrequire
がnode.js
で利用可能なもので、ブラウザやクライアントサイドのJavaScript
ではそのまま利用できないことをこちらの記事で知りました。
同記事にもある、browserify
でbundleして利用可能なものとすべく、npm
でそれぞれ以下を叩きました。
npm install -g browserify
npm install pdf.js-extract
browserify parse.js -o bundle.js
すると最終的に以下のコマンドプロンプトで以下メッセージが出力され、bundleすることができずに、行き詰ってしまいました。
C:\Users\XXX\Desktop\PJT_PP>browserify parse.js -o bundle.js Error: Can't walk dependency graph: Cannot find module 'canvas' from 'C:\Users\XXX\Desktop\PJT_PP\node_modules\pdf.js-extract\lib\pdfjs\pdf.js' required by C:\Users\XXX\Desktop\PJT_PP\node_modules\pdf.js-extract\lib\pdfjs\pdf.js at C:\Users\XXX\AppData\Roaming\npm\node_modules\browserify\node_modules\resolve\lib\async.js:146:35 at processDirs (C:\Users\XXX\AppData\Roaming\npm\node_modules\browserify\node_modules\resolve\lib\async.js:299:39) at isdir (C:\Users\XXX\AppData\Roaming\npm\node_modules\browserify\node_modules\resolve\lib\async.js:306:32) at C:\Users\XXX\AppData\Roaming\npm\node_modules\browserify\node_modules\resolve\lib\async.js:34:69 at FSReqCallback.oncomplete (node:fs:199:21)
本質的にはJavaScriptでPDFのテキストを抽出したいというところではあるのですが、他にあまりより代替案も見つけることができず、このbrowserify
をうまく突破するためのアドバイスをいただけると幸いです。
npmの状況
package.json
1{ 2 "dependencies": { 3 "browserify": "^17.0.0", 4 "http-server": "^14.1.1", 5 "pdf.js-extract": "^0.2.1", 6 "uniq": "^1.0.1" 7 } 8}
よろしくお願い申し上げます。
【追記】
修正コード
html
1<!--index.html--> 2<!DOCTYPE html> 3<html lang="ja"> 4 5<head> 6 <meta charset="UTF-8"> 7 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 8 <title>Document</title> 9 <script src="https://cdn.jsdelivr.net/npm/pdfjs-dist@2.13.216/legacy/build/pdf.min.js"></script> 10</head> 11 12<body> 13 <script type="module" src="http://localhost:8080/parse.js"></script> 14</body> 15 16</html>
JavaScript
1 import pdfjsLib from 'pdfjs-dist' 2 3 function extractBuffer(buffer, options = {}, cb) { 4 if (!cb) { 5 return new Promise((resolve, reject) => { 6 this.extractBuffer(buffer, options, (err, data) => { 7 if (err) { 8 reject(err); 9 } else { 10 resolve(data); 11 } 12 }) 13 }); 14 } 15 // Loading file from file system into typed array 16 if (options.verbosity === undefined) { 17 // get rid of all warnings in nodejs usage 18 options.verbosity = -1; 19 } 20 if (options.cMapUrl === undefined) { 21 options.cMapUrl = path.join(__dirname, "./cmaps/"); // trailing path delimiter is important 22 } 23 if (options.cMapPacked === undefined) { 24 options.cMapPacked = true; 25 } 26 if (options.CMapReaderFactory === undefined) { 27 options.CMapReaderFactory = LocalCMapReaderFactory; 28 } 29 options.data = new Uint8Array(buffer); 30 const pdf = { 31 meta: {}, 32 pages: [] 33 }; 34 // Will be using promises to load document, pages and misc data instead of callback. 35 pdfjsLib.getDocument(options).promise.then(doc => { 36 const firstPage = (options && options.firstPage) ? options.firstPage : 1; 37 const lastPage = Math.min((options && options.lastPage) ? options.lastPage : doc.numPages, doc.numPages); 38 pdf.pdfInfo = doc.pdfInfo; 39 const promises = [ 40 doc.getMetadata().then(data => { 41 pdf.meta = {info: data.info, metadata: data.metadata ? data.metadata.getAll() || null : null}; 42 }) 43 ]; 44 const loadPage = pageNum => doc.getPage(pageNum).then(page => { 45 const viewport = page.getViewport({scale: 1.0}); 46 const pag = { 47 pageInfo: { 48 num: pageNum, 49 scale: viewport.scale, 50 rotation: viewport.rotation, 51 offsetX: viewport.offsetX, 52 offsetY: viewport.offsetY, 53 width: viewport.width, 54 height: viewport.height 55 } 56 }; 57 pdf.pages.push(pag); 58 const normalizeWhitespace = !!(options && options.normalizeWhitespace === true); 59 const disableCombineTextItems = !!(options && options.disableCombineTextItems === true); 60 return Promise.all([ 61 page.getAnnotations().then((annotations) => { 62 pag.links = annotations.filter((annot) => annot.subtype === "Link" && !!annot.url) 63 .map((link) => link.url); 64 }), 65 page.getTextContent({normalizeWhitespace, disableCombineTextItems}).then((content) => { 66 // Content contains lots of information about the text layout and styles, but we need only strings at the moment 67 pag.content = content.items.map(item => { 68 const tm = item.transform; 69 let x = tm[4]; 70 let y = pag.pageInfo.height - tm[5]; 71 if (viewport.rotation === 90) { 72 x = tm[5]; 73 y = tm[4]; 74 } 75 // see https://github.com/mozilla/pdf.js/issues/8276 76 const height = Math.sqrt(tm[2] * tm[2] + tm[3] * tm[3]); 77 return { 78 x: x, 79 y: y, 80 str: item.str, 81 dir: item.dir, 82 width: item.width, 83 height: height, 84 fontName: item.fontName 85 }; 86 }); 87 }) 88 ]).then(() => { 89 // console.log("done page content parsing"); 90 }, (err) => { 91 cb(err); 92 }); 93 }); 94 for (let i = firstPage; i <= lastPage; i++) { 95 promises.push(loadPage(i)); 96 } 97 return Promise.all(promises); 98 }).then(() => { 99 pdf.pages.sort((a, b) => a.pageInfo.num - b.pageInfo.num); 100 cb(null, pdf); 101 }, (err) => { 102 cb(err) 103 }); 104 } 105 106
回答1件
あなたの回答
tips
プレビュー