React中pdf.js解析PDF文本的格式与简历分段问题求助
解决PDF简历文本提取错位与模块划分问题
一、修复pdf.js文本提取的错位问题
你当前的代码直接将每个文本元素换行,导致错位——因为PDF的文本元素是按绘制顺序存储,而非自然行顺序。需要根据文本的Y坐标分组,将同一行的文本合并:
修改getTextContent后的处理逻辑:
const pageText = await page.getTextContent(); // PDF坐标原点在左下角,Y值越大越靠上,先按Y倒序排序 const sortedItems = pageText.items.sort((a, b) => b.transform[5] - a.transform[5]); let currentLineY = null; let currentLine = []; const pageLines = []; sortedItems.forEach(item => { const itemY = item.transform[5]; // 设定阈值(如2px),判断是否属于同一行 if (currentLineY === null || Math.abs(itemY - currentLineY) < 2) { currentLine.push(item); } else { // 同一行文本按X坐标从左到右排序后拼接 pageLines.push(currentLine.sort((a, b) => a.transform[4] - b.transform[4]).map(i => i.str).join(' ')); currentLine = [item]; currentLineY = itemY; } }); // 加入最后一行内容 if (currentLine.length > 0) { pageLines.push(currentLine.sort((a, b) => a.transform[4] - b.transform[4]).map(i => i.str).join(' ')); } extractedText += pageLines.join('\n');
二、简历文本的模块划分
简历模块有明确的关键词标识,可通过关键词匹配+文本结构分析实现划分:
1. 关键词匹配法
先定义常见的简历模块关键词集合,再遍历文本分割模块:
// 定义模块与对应关键词 const moduleKeywords = { personalInfo: ['个人简介', '基本信息', '个人信息'], education: ['教育经历', '教育背景', '学历背景'], workExperience: ['工作经历', '职业经历', '工作背景'], skills: ['技能特长', '专业技能', '核心技能'], projects: ['项目经验', '项目经历'] }; function splitResumeModules(text) { const modules = { other: [] }; let currentModule = 'other'; text.split('\n').forEach(line => { let matched = false; // 检查当前行是否匹配模块标题 Object.entries(moduleKeywords).forEach(([moduleName, keywords]) => { if (keywords.some(key => line.includes(key))) { currentModule = moduleName; modules[currentModule] = [line]; matched = true; } }); if (!matched) modules[currentModule].push(line); }); // 合并每个模块的文本 Object.keys(modules).forEach(key => { modules[key] = modules[key].join('\n').trim(); }); return modules; } // 使用示例 const resumeModules = splitResumeModules(extractedText); console.log(resumeModules.personalInfo); console.log(resumeModules.education);
2. 结合字体样式分析
pdf.js返回的文本元素包含字体大小(通过transform[3]计算)和字体名称,标题通常字体更大、加粗,可通过此筛选模块标题:
// 筛选可能的标题元素(字体大小>14px) const titleItems = pageText.items.filter(item => { const fontSize = item.transform[3] * 16; // 16为默认基准字号 return fontSize > 14; }); // 从标题元素中提取关键词,再进行模块划分
三、替代PDF解析方案
如果pdf.js效果仍不理想,可尝试以下前端方案:
1. pdf-parse
基于pdf.js封装的轻量库,默认处理行对齐问题:
npm install pdf-parse
使用示例:
import pdfParse from 'pdf-parse'; const handleFileChange = async (event) => { const selectedFile = event.target.files[0]; if (!selectedFile) return; const dataBuffer = await selectedFile.arrayBuffer(); pdfParse(dataBuffer).then(data => { setExtractedText(data.text); // 后续模块划分逻辑 }).catch(error => { console.error('Error parsing PDF:', error); }); };
2. react-pdf
专为React设计的PDF处理库,对布局处理更友好:
npm install @react-pdf/renderer
文本提取示例:
import { pdf } from '@react-pdf/renderer'; const extractTextFromPDF = async (file) => { const arrayBuffer = await file.arrayBuffer(); const doc = await pdf(arrayBuffer); let text = ''; for (let i = 1; i <= doc.getPageCount(); i++) { const page = await doc.getPage(i); text += await page.getTextContent(); } return text; };
3. 扫描件OCR处理(针对图片式PDF)
如果简历是扫描生成的图片PDF,使用tesseract.js进行OCR识别:
npm install tesseract.js
使用示例:
import Tesseract from 'tesseract.js'; const handleScannedPDF = async (file) => { const pdf = await pdfjs.getDocument({ data: await file.arrayBuffer() }).promise; for (let i = 1; i <= pdf.numPages; i++) { const page = await pdf.getPage(i); const viewport = page.getViewport({ scale: 2 }); const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); canvas.height = viewport.height; canvas.width = viewport.width; await page.render({ canvasContext: ctx, viewport }).promise; // OCR识别中文文本 const { data: { text } } = await Tesseract.recognize(canvas, 'chi_sim'); console.log(text); } };
内容的提问来源于stack exchange,提问作者Yash Singhal
相关产品推荐
相关产品推荐

