Python提取PDF订单仅捕获首个产品及CSV导出乱码问题求解
PDF订单解析问题解决方案
问题1:仅能提取每页首个产品的修复
根本原因
- 原代码的公共字段(PO、交货日期、PO日期、收货地址)和产品字段的存储逻辑错误:遍历完一页所有行后才生成1条记录,只会保留最后匹配到的产品信息,多条产品数据被覆盖
- PODate的判断分支和PO的匹配条件完全一致,永远不会触发,无法正确提取PO日期
修复方案
- 每页遍历前初始化公共字段变量,匹配到对应内容时赋值
- 每匹配到一条产品行,立即用当前已赋值的公共字段+当前产品字段生成记录,追加到结果列表
- 修正PODate的匹配规则,避免和PO的匹配条件冲突
问题2:CSV导出非英文字符乱码/空格异常修复
根本原因
- 默认导出CSV使用的编码不支持越南语字符,普通UTF-8编码在Windows平台的Excel中打开会出现乱码
- 提取的文本未做空白字符清理,保留了PDF解析出来的多余不可见空白
修复方案
- 导出CSV时指定
encoding='utf-8-sig',带BOM的UTF-8编码可被绝大多数表格工具正确识别 - 提取每个字段后调用
strip()清理前后空白,必要时用正则替换连续空白为单个空格
修正后完整代码
import re import pdfplumber import pandas as pd from collections import namedtuple path = "/Users/mymacbook/Downloads/onefolder/123.pdf" Line = namedtuple('Line', 'PO DeliveryDate PODate ShipTo Barcode Description SMCode Quantity Price') # 正则规则可根据实际PDF文本内容微调 PO_re = re.compile(r'(\d+\.\d+).+(\d{2}\.\d{2}\.\d{4})') ord_re = re.compile(r'(\d+) (.*) (\d{5,6}) (\d+\,\d+) (\d+\,\d+)') ShipTo_re = re.compile(r'(\w+) (Company Name MM) (.*)') PODate_re = re.compile(r'PO Date.*?(\d{1,2}\.\d{1,2}\.\d{4})') # 调整为匹配PO Date开头的行,避免和第一个正则冲突 lines = [] with pdfplumber.open(path) as pdf: for page in pdf.pages: text = page.extract_text() # 每页初始化公共字段 PO = DeliveryDate = PODate = ShipTo = None for line in text.split('\n'): line = line.strip() if not line: continue # 匹配PO和交货日期 po_match = PO_re.search(line) if po_match and not PO: # 避免同页重复匹配 PO = po_match.group(1).strip() DeliveryDate = po_match.group(2).strip() continue # 匹配PO日期 podate_match = PODate_re.search(line) if podate_match and not PODate: PODate = podate_match.group(1).strip() continue # 匹配收货地址 if line.startswith('Name', 30) and not ShipTo: ShipTo = line.split(' Name ')[-1].strip() continue # 匹配产品行,匹配到就生成记录 ord_match = ord_re.search(line) if ord_match: haha = ord_match.group(1).strip() Barcode = haha[-13:] Description = ord_match.group(2).strip() # 清理描述里的多余空格 Description = re.sub(r'\s+', ' ', Description) SMCode = ord_match.group(3).strip() Quantity = ord_match.group(4).strip() Price = ord_match.group(5).strip() # 公共字段都匹配到再生成记录,避免空值 if all([PO, DeliveryDate, PODate, ShipTo]): lines.append(Line(PO, DeliveryDate, PODate, ShipTo, Barcode, Description, SMCode, Quantity, Price)) # 生成DataFrame df = pd.DataFrame(lines) # 导出CSV,指定编码解决乱码 df.to_csv('订单汇总.csv', index=False, encoding='utf-8-sig')
内容的提问来源于stack exchange,提问作者mng2109
相关产品推荐
相关产品推荐

