如何使用pdfplumber编写for循环提取PDF数据并解决TypeError报错
错误根因
你的核心问题是遍历每行的字符串变量line被反复覆盖为正则匹配结果(re.Match对象或者None),后续正则调用search()时传入的不再是字符串,直接触发类型错误。
同时还有几个影响功能的问题:
- 正则规则写死了空格长度,PDF提取文本的空格数量不固定,会导致匹配失败
- 语言行正则漏写了开头的
E,无法正确匹配 - 数字匹配规则只适配固定位数,无法适配你样例里的数字格式
- 变量未提前初始化,未匹配到对应行时会报变量未定义
- 每遍历一行就往
line_items追加数据,会生成大量无效重复条目
修复后代码
import re import pdfplumber import pandas as pd from collections import namedtuple # 定义输出结构 Serv = namedtuple('Serv', 'case_number language num_trans num_fuzzy num_exact') line_items = [] # 优化后的正则规则,用\s+匹配任意数量空白,适配数字格式 case_li = re.compile(r'(\d{6}\w{2}\d{2})') language_li = re.compile(r'English \(US\) into (.*)') trans_li = re.compile(r'Trans\./Edit/Proof\.\s+([\d.,]+)\s+Words') fuzzy_li = re.compile(r'TM - Fuzzy Match\s+([\d.,]+)\s+Words') exact_li = re.compile(r'TM - Exact Match\s+([\d.,]+)\s+Words') with pdfplumber.open('test.pdf') as pdf: for page in pdf.pages: text = page.extract_text() # 每页初始化变量,避免跨页串数据,单份数据跨多页可将这行移到页循环外 case_number = language = num_trans = num_fuzzy = num_exact = None for line in text.split('\n'): # 不要覆盖原line变量,单独用match变量存结果 match = case_li.search(line) if match: case_number = match.group(1) match = language_li.search(line) if match: language = match.group(1) match = trans_li.search(line) if match: num_trans = match.group(1) match = fuzzy_li.search(line) if match: num_fuzzy = match.group(1) match = exact_li.search(line) if match: num_exact = match.group(1) # 单页所有行匹配完后再追加有效条目 if any([case_number, language, num_trans, num_fuzzy, num_exact]): line_items.append(Serv(case_number, language, num_trans, num_fuzzy, num_exact)) # 生成DataFrame df = pd.DataFrame(line_items) print(df)
补充说明
如果需要把提取到的数字字符串转为数值格式,只需要加一步把数字里的逗号替换为小数点,再转float类型即可。
内容的提问来源于stack exchange,提问作者Edo Grm
相关产品推荐
相关产品推荐

