Python多行正则提取PDF文本块报错求助:重复匹配问题
问题与解答:PDF文本块正则提取报错分析
需求说明
想要从PDF中提取以下格式的所有文本块:
Aug 12, 2022 Name of Place €11.22 €123.12 To: Long Name of Place Card: 123456******1234
已实现的单部分提取正则
# dates reg_date = re.compile(r'((Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{1,2}\, \d{4})') # currency reg_cur = re.compile(r'[\$\u20AC\u00A3]{1}\d+\.?\d{0,2}') # vendor reg_vdr = re.compile(r'To\:(.*)') # card reg_crd = re.compile(r'Card\:(.*)')
遇到的问题
尝试提取完整文本块时,编写的正则报错multiple repeat at position 77,代码如下:
# block reg_block = re.compile(r'(?<=(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{1,2}\, \d{4}(.*?)?=******\d{4})') matches = reg_date.findall(raw['content']) print(matches)
问题分析与解决方案
1. 正则报错的直接原因
报错的核心是你写的=******部分:*是正则的重复元字符(表示匹配前一个字符0或多次),连续写多个*会让正则引擎无法解析,属于语法错误。要匹配卡号里的******,需要把*转义为普通字符,写成\*\*\*\*\*\*,或者用\*{6}更简洁。
除此之外,你的正则还有两处明显问题:
- 正向预查
(?<=...)的逻辑混乱,没有覆盖完整的文本块结构,而且(.*?)?是无效写法——.*?已经是非贪婪匹配,再加?完全多余。 - 未处理换行符:PDF提取的文本中换行通常是
\n,正则默认不允许.匹配换行符,需要添加re.DOTALL(或re.S)标志来修正。
2. 正确的完整文本块正则示例
要匹配整个目标文本块,可以使用以下正则:
import re # 匹配完整块的正则,适配换行、转义特殊字符,明确结构 reg_block = re.compile( r'(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{1,2}, \d{4} .+? [\$\u20AC\u00A3]\d+\.?\d{0,2} [\$\u20AC\u00A3]\d+\.?\d{0,2}\r?\nTo: .+\r?\nCard: \d{6}\*{6}\d{4}', re.DOTALL ) # 提取块后用已有正则拆分各部分 raw_content = """你的PDF提取文本内容""" blocks = reg_block.findall(raw_content) for block in blocks: date_match = reg_date.search(block) vendor_match = reg_vdr.search(block) cur_matches = reg_cur.findall(block) card_match = reg_crd.search(block) if all([date_match, vendor_match, cur_matches, card_match]): print(f"日期: {date_match.group(0)}") print(f"商家: {vendor_match.group(1).strip()}") print(f"金额: {cur_matches}") print(f"卡号: {card_match.group(1).strip()}") print("---")
3. 额外优化建议
- 日期匹配可以添加
re.IGNORECASE标志,兼容PDF中可能出现的小写月份(比如aug)。 - 卡号部分固定为
6位数字+6个*+4位数字,用\d{6}\*{6}\d{4}比模糊匹配更精准。 - 用
\r?\n替代\n,适配Windows系统的\r\n换行格式。
内容的提问来源于stack exchange,提问作者Tobias Funke
相关产品推荐
相关产品推荐

