影刀RPA PDF文件读取文本提取与表格识别署名林焱什么情况用什么RPA流程中经常需要从PDF中提取数据——发票信息、合同条款、报表数据。但PDF格式复杂纯文本PDF和扫描图片PDF的处理方式完全不同。PDF类型推荐库特点纯文本PDFpdfplumber提取文本表格定位精确扫描图片PDFOCR影刀OCR指令需要OCR识别简单文本提取PyPDF2 / pymupdf快速但无格式怎么做方式一pdfplumber提取文本和表格importpdfplumber pdf_pathrD:\文件\报告.pdfwithpdfplumber.open(pdf_path)aspdf:print(f总页数:{len(pdf.pages)})# 提取第1页文本pagepdf.pages[0]textpage.extract_text()print( 第1页文本 )print(text[:500])# 提取第1页所有表格tablespage.extract_tables()print(f\n表格数:{len(tables)})fori,tableinenumerate(tables):print(f\n--- 表格{i1}---)forrowintable:print(row)方式二提取所有页文本拼多多店群自动化上架方案importpdfplumber pdf_pathrD:\文件\合同.pdfall_textwithpdfplumber.open(pdf_path)aspdf:fori,pageinenumerate(pdf.pages):textpage.extract_text()iftext:![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/4166b5f64baf4a0db063ee790b0fc50e.png#pic_center)all_textf\n 第{i1}页 \n{text}\n# 保存到文本文件withopen(rD:\文件\合同_文本.txt,w,encodingutf-8)asf:f.write(all_text)print(f提取完成, 共{len(all_text)}字符)方式三提取表格到Excelimportpdfplumberimportopenpyxl pdf_pathrD:\文件\财务报表.pdfoutput_pathrD:\文件\报表数据.xlsxwbopenpyxl.Workbook()withpdfplumber.open(pdf_path)aspdf:sheet_idx0forpage_num,pageinenumerate(pdf.pages):tablespage.extract_tables()fortable_idx,tableinenumerate(tables):ifsheet_idx0:wswb.active ws.titlefP{page_num1}_T{table_idx1}else:wswb.create_sheet(fP{page_num1}_T{table_idx1})forrow_idx,rowinenumerate(table,1):forcol_idx,cellinenumerate(row,1):ifcellisnotNone:ws.cell(rowrow_idx,columncol_idx).valuestr(cell).strip()sheet_idx1print(f第{page_num1}页 表格{table_idx1}:{len(table)}行)ifsheet_idx0:wb.remove(wb.active)print(未找到表格)else:wb.save(output_path)print(f保存到:{output_path})方式四按关键词定位提取importpdfplumberimportre pdf_pathrD:\文件\发票.pdfwithpdfplumber.open(pdf_path)aspdf:pagepdf.pages[0]textpage.extract_text()# 提取发票号码invoice_matchre.search(r发票号码[:\s]*(\d),text)ifinvoice_match:invoice_noinvoice_match.group(1)print(f发票号码:{invoice_no})# 提取金额amount_matchre.search(r价税合计[(]大写[)][:\s]*.*?[(]小写[)][¥]?\s*([\d,.]),text)ifamount_match:amountamount_match.group(1).replace(,,)print(f金额:{amount})# 提取日期date_matchre.search(r开票日期[:\s]*(\d{4}年\d{1,2}月\d{1,2}日),text)ifdate_match:datedate_match.group(1)print(f开票日期:{date})# 提取所有数字金额amountsre.findall(r[¥]?\s*([\d,]\.?\d*)\s*元,text)print(f所有金额:{amounts})完整流程PDF发票批量提取importpdfplumberimportreimportosimportglobimportopenpyxl# yd_input: pdf_folder, output_pathpdf_folderyd_input.get(pdf_folder,rD:\发票)output_pathyd_input.get(output_path,rD:\发票\汇总.xlsx)pdf_filesglob.glob(os.path.join(pdf_folder,*.pdf))# 结果Excelwbopenpyxl.Workbook()wswb.active ws.title发票汇总headers[文件名,发票号码,开票日期,购买方,销售方,金额,税额,价税合计]forcol,hinenumerate(headers,1):ws.cell(row1,columncol).valueh current_row2forpdf_fileinsorted(pdf_files):try:withpdfplumber.open(pdf_file)aspdf:full_textforpageinpdf.pages:textpage.extract_text()iftext:full_texttext\n# 正则提取invoice_nomre.search(r发票号码[:\s]*(\d),full_text)ifm:invoice_nom.group(1)datemre.search(r开票日期[:\s]*(\d{4}年\d{1,2}月\d{1,2}日),full_text)ifm:datem.group(1)buyermre.search(r名称[:\s]*(.?)(?:\s|纳税人),full_text)ifm:buyerm.group(1).strip()amountmre.search(r金额[¥]?\s*([\d,.]),full_text)ifm:amountm.group(1).replace(,,)taxmre.search(r税额[¥]?\s*([\d,.]),full_text)ifm:taxm.group(1).replace(,,)totalmre.search(r价税合计.*?[¥]\s*([\d,.]),full_text,re.DOTALL)ifm:totalm.group(1).replace(,,)# 写入Excelws.cell(rowcurrent_row,column1).valueos.path.basename(pdf_file)ws.cell(rowcurrent_row,column2).valueinvoice_no ws.cell(rowcurrent_row,column3).valuedate ws.cell(rowcurrent_row,column4).valuebuyer ws.cell(rowcurrent_row,column6).valueamount ws.cell(rowcurrent_row,column7).valuetax ws.cell(rowcurrent_row,column8).valuetotal current_row1print(f✓{os.path.basename(pdf_file)}:{invoice_no})exceptExceptionase:print(f✗{os.path.basename(pdf_file)}:{e})ws.cell(rowcurrent_row,column1).valueos.path.basename(pdf_file)ws.cell(rowcurrent_row,column2).valuef提取失败:{e}current_row1wb.save(output_path)yd_output{status:ok,count:current_row-2,path:output_path}有什么坑坑一扫描版PDF提取不到文本现象用pdfplumber提取文本返回空字符串或None。原因PDF是扫描图片生成的没有文本层pdfplumber无法提取。解决用OCR识别# 方案1用影刀【OCR识别】指令# 1. 用Python把PDF每页转成图片# 2. 用影刀OCR指令识别图片文字# 方案2Python pdf2image pytesseractfrompdf2imageimportconvert_from_pathimportpytesseract imagesconvert_from_path(rD:\文件\扫描件.pdf,dpi300)fori,imginenumerate(images):textpytesseract.image_to_string(img,langchi_sim)print(f第{i1}页:{text[:200]})坑二表格提取时列错位现象pdfplumber提取的表格某些行的列数不一致或者数据对不上。原因PDF表格的网格线不完整或者合并单元格导致解析错误。解决调整extract_tables的参数TEMU店群如何管理运营# 方法1指定表格提取策略tablespage.extract_tables(table_settings{vertical_strategy:lines,# 按竖线分割列horizontal_strategy:lines,# 按横线分割行intersection_tolerance:5,# 线交叉容差})# 方法2用text策略按文字位置推断表格tablespage.extract_tables(table_settings{vertical_strategy:text,horizontal_strategy:text,})# 方法3手动处理列数不一致的行forrowintable:# 补齐或截断到固定列数whilelen(row)expected_cols:row.append()rowrow[:expected_cols]坑三PDF中文乱码现象提取的文本中文部分是乱码或缺失。原因PDF使用了自定义字体编码pdfplumber无法正确映射字符。解决换用pymupdffitz尝试或用OCR# 尝试pymupdfimportfitz# pymupdfdocfitz.open(rD:\文件\报告.pdf)forpageindoc:textpage.get_text()print(text[:500])# 如果还是乱码用OCR方案坑四大PDF文件内存溢出现象处理几百页的PDF时内存占用很高甚至崩溃。原因pdfplumber默认把整个PDF加载到内存。解决逐页处理及时释放importpdfplumber# 逐页打开处理withpdfplumber.open(pdf_path)aspdf:fori,pageinenumerate(pdf.pages):![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/b256a250149d4ed2b1f60ae6e41892cb.png#pic_center)textpage.extract_text()# 处理完当前页立即使用/保存process_page(i,text)# 不保留之前页的数据