在线PDF答案提取及频次统计代码优化技术咨询
完善PDF竞赛答案提取与频次统计代码
需求背景
为辅助历史竞赛团队备考,需实现以下功能:
- 从目标PDF中提取所有
ANSWER:后的文本内容 - 统计各答案的出现频次
- 支持在网页中展示结果,或导出至Excel文档
原代码问题分析
原代码存在以下不足:
- 答案提取逻辑错误:通过循环调用
indexOf仅获取单个字符,无法提取完整答案 - 无频次统计功能
- 结果展示简陋,仅输出原始文本
- 缺少Excel导出功能
修改后的完整代码
<html> <head> <script src="https://npmcdn.com/pdfjs-dist/build/pdf.js"></script> <style> table { border-collapse: collapse; margin: 20px 0; } th, td { border: 1px solid #ddd; padding: 8px; text-align: left; } th { background-color: #f2f2f2; } .export-btn { padding: 8px 16px; background-color: #4CAF50; color: white; border: none; cursor: pointer; margin: 10px 0; } </style> </head> <body> <input id="pdffile" name="pdffile" type="file" accept=".pdf" /> <button id="btn" onclick="convert()">Process</button> <button id="exportBtn" class="export-btn" onclick="exportToExcel()" disabled>Export to Excel</button> <div id="result"></div> </body> </html> <script> let answerFrequency = {}; let fullAnswers = []; function convert() { const fileInput = document.getElementById('pdffile'); if (!fileInput.files.length) { alert('请先选择PDF文件'); return; } const fr = new FileReader(); const pdff = new Pdf2TextClass(); fr.onload = function() { pdff.pdfToText(fr.result, null, (text) => { extractAnswers(text); displayResults(); document.getElementById('exportBtn').disabled = false; }); } fr.readAsArrayBuffer(fileInput.files[0]); } function extractAnswers(text) { // 重置统计数据 answerFrequency = {}; fullAnswers = []; // 正则匹配所有ANSWER: 后的内容,直到换行或段落结束 const answerRegex = /ANSWER:\s*(.+?)(?=\n|\r|$)/g; let match; while ((match = answerRegex.exec(text)) !== null) { const answer = match[1].trim(); fullAnswers.push(answer); // 统计频次 answerFrequency[answer] = (answerFrequency[answer] || 0) + 1; } } function displayResults() { const resultDiv = document.getElementById('result'); resultDiv.innerHTML = ''; // 展示原始答案列表 const answersList = document.createElement('div'); answersList.innerHTML = `<h3>提取的所有答案</h3><ul>${fullAnswers.map(ans => `<li>${ans}</li>`).join('')}</ul>`; resultDiv.appendChild(answersList); // 展示频次统计表格 const frequencyTable = document.createElement('div'); const sortedEntries = Object.entries(answerFrequency).sort((a, b) => b[1] - a[1]); frequencyTable.innerHTML = ` <h3>答案频次统计</h3> <table> <tr><th>答案</th><th>出现次数</th></tr> ${sortedEntries.map(([ans, count]) => `<tr><td>${ans}</td><td>${count}</td></tr>`).join('')} </table> `; resultDiv.appendChild(frequencyTable); } function exportToExcel() { // 构建CSV内容 let csvContent = '答案,出现次数\n'; Object.entries(answerFrequency).forEach(([ans, count]) => { csvContent += `"${ans.replace(/"/g, '""')}",${count}\n`; }); // 创建下载链接 const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.setAttribute('download', 'history-competition-answers.csv'); document.body.appendChild(link); link.click(); document.body.removeChild(link); } function Pdf2TextClass() { var self = this; this.complete = 0; this.pdfToText = function (data, callbackPageDone, callbackAllDone) { console.assert(data instanceof ArrayBuffer || typeof data == 'string'); var loadingTask = pdfjsLib.getDocument(data); loadingTask.promise.then(function (pdf) { var total = pdf._pdfInfo.numPages; var layers = {}; for (let i = 1; i <= total; i++) { pdf.getPage(i).then(function (page) { var n = page.pageNumber; page.getTextContent().then(function (textContent) { if (null != textContent.items) { var page_text = ""; var last_block = null; for (var k = 0; k < textContent.items.length; k++) { var block = textContent.items[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; } layers[n] = page_text + "\n\n"; } ++self.complete; if (self.complete == total) { 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); } }); }); } }); }; }; </script>
关键改进说明
- 答案提取优化:使用正则表达式
/ANSWER:\s*(.+?)(?=\n|\r|$)/g全局匹配ANSWER:后的完整内容,确保提取到每一个答案的全部文本 - 频次统计实现:通过对象
answerFrequency存储每个答案的出现次数,遍历匹配结果时更新计数 - 结果展示优化:将提取的答案以列表形式展示,频次统计以排序后的表格展示,更直观清晰
- Excel导出功能:将统计数据转换为CSV格式,通过创建下载链接实现导出,CSV文件可直接用Excel打开
- 代码健壮性提升:添加文件选择校验,修改
FileReader读取方式为readAsArrayBuffer(更适合pdf.js处理)
内容的提问来源于stack exchange,提问作者Charlie O
相关产品推荐
相关产品推荐

