You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在线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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 18:40:57