
PHP语言本身并没有内置处理PDF文本提取的功能,但是我们可以借助第三方开源扩展库或服务器底层的工具来实现转换。
一、用得最多的smalot/pdfparser库
这是目前PHP社区最成熟、使用最简单的纯PHP库,不需要在服务器安装任何复杂的软件,直接通过Composer引入即可。
composer require smalot/pdfparser然后就可以直接使用了。
set_time_limit(0);ini_set('memory_limit', '1024M'); // 适当调大内存,防止大财报PDF导致内存溢出if(function_exists('ob_end_clean')) { @ob_end_clean(); }date_default_timezone_set('PRC');// 1.【核心】必须先引入 Composer 自动加载器require __DIR__ . '/vendor/autoload.php';// 设定您需要读取的 PDF 名字,以及想要输出的目标 TXT 名字$pdfFile = __DIR__ . '/test.pdf';$txtFile = __DIR__ . '/test_smalot.txt'; //锁死您输出的文本文件名if(!file_exists($pdfFile)) {die(" 错误:在当前目录下没有找到目标 [{$pdfFile}] 文件,请先上传!\n");}echo "正在启动 Smalot Parser 纯 PHP 核心对 [ " . basename($pdfFile) . " ] 进行深度文本解包...\n";try {// 2. 初始化解析器大脑$parser = new \Smalot\PdfParser\Parser();// 3. 内存级全量解析 PDF 文件$pdf = $parser->parseFile($pdfFile);// 4. 【文字抽取】一键将整个 PDF 内部的所有文字转化为纯文本字符串$text = $pdf->getText();$text = trim($text);if(empty($text)) {die("[解析中断警告] 提取出来的文本内容为空!\n结论:该 PDF 100% 是【图片扫描版】。纯 PHP 无法直接提取,请放弃此方法,改用我们之前配好的 Tesseract OCR 本地引擎进行透视识别。\n");}// 5. 【终极输出铁闸】使用 PHP 原生高效率函数,将文字流一键写入本地 TXT 文件// 如果文件不存在会自动创建;如果存在会直接无脑覆盖更新file_put_contents($txtFile, $text);echo " 恭喜!纯 PHP 文本提取大获成功!\n";echo " 已经将全部纯文本数据顺利输出并沉淀至本地文件:[ " . basename($txtFile) . " ] \n";echo "提示:您现在可以直接在宝塔面板、或用记事本点开这个 TXT 文件查看清洗成果了。\n";} catch(\Exception $e) {die("解析或写入失败,捕获到核心异常: " . $e->getMessage() . "\n");}
二、秒速的Spatie pdf-to-text文字识别
composer require spatie/pdf-to-text然后,也可以直接使用了。
// 1. 必须先引入 Composer 的自动加载器,require __DIR__ . '/vendor/autoload.php';// 2. 必须显式声明并引入 Spatie 的命名空间空间包use Spatie\PdfToText\Pdf;// 3. 此时才可以顺利、无报错地直接调用// 设定输入和输出的路径$pdfFile = 'test.pdf';$txtFile = 'spatie_test.txt'; // 锁死您想要输出的文本文件名if(!file_exists($pdfFile)) {die("错误:在当前目录下没有找到 [{$pdfFile}] 文件,请先上传!\n");}try {echo " 正在秒级调动 C 语言底层组件抽取文字...\n";// 3. 执行提取(如果之前 which pdftotext 的路径是 /usr/bin/pdftotext,建议显式加上路径防错)$text = (new Pdf('/usr/bin/pdftotext'))->setPdf($pdfFile)->text();$text = trim($text);if(empty($text)) {die(" [警告] 提取文本为空!该 PDF 极大概率是【纯图片扫描版】,Spatie 无法处理,请改用之前配好的 Tesseract OCR 本地引擎。\n");}// 4. 【终极输出核心】使用 PHP 原生函数将文本字符串强力写入本地 TXT 文件// FILE_USE_INCLUDE_PATH 和它的底层编码会自动兼容,如果文件不存在会自动创建,如果存在会直接无脑覆盖file_put_contents($txtFile, $text);echo "文字提取大获成功!\n";echo " 已经将全部纯文本数据顺利输出并沉淀至同目录下的文件:[{$txtFile}] \n";} catch(\Exception $e) {die("写入失败,异常原因: " . $e->getMessage() . "\n");}
三、Tesseract 图片识别工具
Tesseract是由谷歌维护的三方开源库,对纯数字表格和标准英文字体的分辨力极高。如果你的图片PDF里是纯英文或标准数字,这识别率就惊人了,几乎可以媲美商业软件。
加载了官方的中文语言包chi_sim后,处理常规清晰的中文段落,准确率能够保持在80%左右。但如果出现冷门字、繁体字或艺术字,错字率会明显上升一些。
如果是上市公司图片类财报,准确度只有40% - 60%。 上市公司的财务报表包含大量密密麻麻的数字、虚线隔断、多栏并排以及会计科目表格,将隔列的数字拼接容易导致数据串行,准确率会暴跌至不及格。
建议采用先用python切图片,再用php读文字,准确率会大幅提升。
1、在Linux服务器上安装Tesseract核心及中文包
这些工具都是读取OCR图片PDF用的,纯文字pdf文件用不到。
{1. 安装 EPEL 高性能扩展源}yum install -y epel-release{2. Tesseract OCR 引擎核心内核及工具链}yum install -y tesseract tesseract-devel{3. 安装官方正统的“简体中文”和“繁体中文”识别字库语言包}yum install -y tesseract-langpack-chi_sim tesseract-langpack-chi_tra{4. 安装Linux 底层高性能 pdf 转换工具链包}yum install -y poppler-utils
如果是宝塔面板,exec、system、passthru及shell_exec这几个关键函数要取消禁用。
运行环境调试好后,pdf转text的工具其实就完成大半了,后面都是照葫芦画瓢,往来重复就是了。
2、在 PHP 项目中部署Tesseract调用扩展
composer require thiagoalessio/tesseract-ocr3、用OCR工具识别测试一张本地图片PDF
先用 PHP将 PDF文件拆成图片,利用服务器自带的pdftoppm命令,速度极快,然后让Tesseract去识别图片上的文字。
set_time_limit(0);ini_set('memory_limit', '1024M'); // 调大内存防止高清切图时崩溃if(function_exists('ob_end_clean')) { @ob_end_clean(); }date_default_timezone_set('PRC');// 1. 【核心】必须先引入刚刚用下划线下载成功的 Composer 自动加载器require __DIR__ . '/vendor/autoload.php';// 2.【核心】显式引入 Tesseract 命名空间包use TesseractOCR\TesseractOCR;// 配置输入与输出的路径$pdfPath = __DIR__ . '/sz.000001_finance.pdf'; // 您放在同目录下的扫描版/图片PDF$outputImagePrefix = __DIR__ . '/temp_page'; // 临时高清切图前缀$txtFile = __DIR__ . '/sz.000001_ocr_finance.txt'; // 锁死您想要输出的文本文件名if(!file_exists($pdfPath)) {die("错误:在当前目录下没有找到目标文件 [ " . basename($pdfPath) . " ],请先上传!\n");}echo "正在执行【落库级预处理】:调用底层工具将 PDF 第一页转换为 300DPI 高清图片...\n";// 3. 调用系统 pdftoppm 工具对 PDF 进行 300DPI 极速高清切图(Tesseract 的黄金识别分辨率)$cmd = "pdftoppm -png -r 300 -f 1 -l 1 " . escapeshellarg($pdfPath) . " " . escapeshellarg($outputImagePrefix);exec($cmd, $output, $returnVar);$generatedImage = $outputImagePrefix . "-1.png"; // 转换后生成的图片真身if($returnVar !== 0 || !file_exists($generatedImage)) {// 容错:如果触发此报错,说明系统漏装了 poppler-utils 组件,去黑窗口执行 [yum install -y poppler-utils] 即可die("图像预处理失败!请确认系统是否安装了 poppler-utils 组件。\n");}echo "高清切图成功!开始启动 Tesseract OCR 本地引擎进行文字和数字透视...\n";try {// 4. 实例化标准的 Tesseract OCR 对象并传入图片路径$ocr = new TesseractOCR($generatedImage);// 5. 【强力对齐】锁死语言包:联合使用我们之前成功挂载的“简体中文(chi_sim)”和“英文(eng)”$ocr->lang('chi_sim', 'eng');// 财务防错白名单铁闸:如果您的 PDF 表格那一页里全部是纯财务数据数字,// 建议去掉下面这行代码前面的注释符号“//”,开启白名单,识别准确率会暴增 15% 以上!// $ocr->config('tessedit_char_whitelist', '0123456789.-%');// 6. 终极一键识别$resultText = $ocr->run();$resultText = trim($resultText);if(empty($resultText)) {echo "[识别警告] 提取出来的文本内容为空!可能图片分辨率有偏差。\n";} else {// 7. 【终极输出核心】使用 PHP 原生高效率函数,将 OCR 识别出的文本一键写入本地 TXT 文件file_put_contents($txtFile, $resultText);echo "恭喜!本地 Tesseract OCR 文字识别与长时序打捞大获成功!\n";echo " 已经将全部透视数据顺利输出并沉淀至本地文本:[ " . basename($txtFile) . " ] \n";echo "提示:您现在可以直接在宝塔面板刷新,点开这个新生成的 TXT 文本查看成果了。\n";}// 8. 顺手物理回收删除临时切图,死守服务器磁盘空间if(file_exists($generatedImage)) { unlink($generatedImage); }} catch(Exception $e) {// 安全沙盒:清理残留的临时文件if(file_exists($generatedImage)) { unlink($generatedImage); }die("OCR 本地引擎在解析时遭遇意外中断: " . $e->getMessage() . "\n");}
原理就是将pdf一页一页切成图片,然后从图片中识别出文字。Tesseract OCR 引擎先要本地化,服务器上要使用Tesseract必须先切图片,将pdf分页切成一张张图片。
一种是纯PHP提取图片的方法。
set_time_limit(0);ini_set('memory_limit', '1024M');if(function_exists('ob_end_clean')) { @ob_end_clean(); }date_default_timezone_set('PRC');// 1. 引入 Composer 自动加载器require __DIR__ . '/vendor/autoload.php';// 设定输入和输出的路径(保持和您的测试文件对齐)$pdfFile = __DIR__ . '/sz.000001_finance.pdf';$txtFile = __DIR__ . '/sz.000001_finance_output.txt';if(!file_exists($pdfFile)) {die("错误:在当前目录下没有找到 [ " . basename($pdfFile) . " ] 测试文件!\n");}echo "[Smalot 纯PHP内核] 正在直接从电子版 PDF 抽取纯文本,无需切图...\n";try {// 2. 初始化解析器$parser = new \Smalot\PdfParser\Parser();// 3. 内存直接解包$pdf = $parser->parseFile($pdfFile);// 4. 一键转为纯文本字符串$text = $pdf->getText();$text = trim($text);if(empty($text)) {die("提取出来的文本内容为空!\n");}// 5. 存盘落入 TXT 文件file_put_contents($txtFile, $text);echo "纯 PHP 文本提取成功!\n";echo "数据已顺利写入同目录下的文件:[ " . basename($txtFile) . " ] \n";} catch(\Exception $e) {die("提取失败,核心异常: " . $e->getMessage() . "\n");}
另外一种是调用pdftotext工具先是安装poppler-utils,也就是上面安装的核心工具之一。
set_time_limit(0);ini_set('memory_limit', '1024M');if(function_exists('ob_end_clean')) { @ob_end_clean(); }date_default_timezone_set('PRC');// 1. 引入自动加载器require __DIR__ . '/vendor/autoload.php';// 2. 引入命名空间use Spatie\PdfToText\Pdf;$pdfFile = __DIR__ . '/sz.000001_finance.pdf';$txtFile = __DIR__ . '/sz.000001_finance_output.txt';if(!file_exists($pdfFile)) {die(" 错误:未找到目标 PDF 文件!\n");}echo " [Spatie C语言直通车] 正在免切图秒级提取文字...\n";try {// 3. 【像素级对齐优化】锁死系统已装好的工具绝对路径,直接直盲抽取文本$text = (new Pdf('/usr/bin/pdftotext'))->setPdf($pdfFile)->text();$text = trim($text);// 4. 一键输出file_put_contents($txtFile, $text);echo " Spatie 直通车提取成功!\n";echo "数据已顺利写入同目录下的文件:[ " . basename($txtFile) . " ] \n";} catch(\Exception $e) {// 容错提示:如果运行报 BinaryNotFound,说明 TencentOS 的 pdftotext 安家在 /usr/local/bin/ 下,改一下上面第 26 行的路径即可die("直通车方案异常报错: " . $e->getMessage() . "\n");}
如果PHP调用pdftoppm切图可能会报错,可能是服务器开放权限不够。那么,可以用采第三种方案,使用Python专属的pdf拆图库pdf2image来进行切图。
安装 Python切图库pdf2image:
pip install pdf2image -i https://huaweicloud.com手工或运行Python脚本把pdf文件进行切图。
python3 -c "from pdf2image import convert_from_path; pages = convert_from_path('sz.000001_finance.pdf', 300); pages[0].save('temp_page-1.png', 'PNG')"PHP运行本地 OCR工具从图片中读出文字。
set_time_limit(0);ini_set('memory_limit', '1024M');if(function_exists('ob_end_clean')) {@ob_end_clean(); }date_default_timezone_set('PRC');// 1. 引入通过下划线成功补齐的 Composer 自动加载器require __DIR__ . '/vendor/autoload.php';// 2. 引入 Tesseract 命名空间包use TesseractOCR\TesseractOCR;// 锁死刚才 Python 帮我们切好的高清测试图片路径$targetImage = __DIR__ . '/temp_page-1.png';$txtFile = __DIR__ . '/sz.000001_ocr_result.txt';// 锁死您最终想要输出的文本文件名if(!file_exists($targetImage)) {die("错误:未找到 Python 切出的高清测试图片 [temp_page-1.png],请先确保第一步 Python 命令执行成功!\n");}echo " 高清切图检测成功!开始启动 Tesseract OCR 本地引擎进行中文及数字深度透视...\n";try {// 3. 实例化标准的 Tesseract OCR 对象并传入图片路径$ocr = new TesseractOCR($targetImage);// 4.【像素级对齐】锁死之前在服务器上完美挂载的两大正统语言包 $ocr->lang('chi_sim', 'eng');// 5. 终极一键本地透视识别$resultText = $ocr->run();$resultText = trim($resultText);if(empty($resultText))echo "[识别警告] 提取出来的文本内容为空!可能字库包加载产生了细微碰撞。\n" } else {// 6. 【终极输出】将本地 OCR 成功透视出的文字一键存入本地 TXT 文件file_put_contents($txtFile, $resultText);echo "恭喜您!图片版 PDF 极限压力测试大获成功!\n";echo "已经将 Tesseract 本地识别出的文字顺利输出至文本:[ " . basename($txtFile) . " ] \n";echo "提示:您现在可以直接在宝塔面板刷新,点开这个TXT 查看抠出来的真实中文字符和数字了!\n"; }// 7. 顺手物理回收临时图片,保持服务器磁盘清爽 if (file_exists($targetImage)) { unlink($targetImage); }catch(Exception $e) {die("OCR 本地引擎在解析时遭遇意外阻断: " . $e->getMessage(). "\n");}
到这,PHP从pdf中读取txt工具就布置完成了,前面两个工具布置非常简洁且很实用,读图片的OCR工具需要较高的网络环境和服务器权限,适合爱折腾的朋友使用,推荐使用Spatie pdf-to-text工具。
总的来说,开始不要嫌麻烦。这种专业工具布置都是先苦然甜的,开始整时有点烦人,整好了办事就起飞了,那才是猪站上了风口,上市公司的财务数据秒秒就变成工整的txt文本了。
夜雨聆风