You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将PDF解析提取的信息整理为指定列的Pandas DataFrame?

问题:从PDF提取的列表构建结构化DataFrame

作为Python新手,我尝试抓取PDF信息并构建DataFrame,已经用tika提取PDF内容得到一个列表,代码如下:

import pandas as pd
import tika
from tika import parser
tika.initVM()

file_name = "the_pdf_im_scraping"

def input_file_processing(file_name):
    parsedPDF = parser.from_file(file_name)
    content = parsedPDF['content']
    contentlist = content.split('\n')
    contentlist = list(filter(lambda a: a != '', contentlist))
    return contentlist

contentlist = input_file_processing(file_name)

提取得到的列表内容:

["John, Doe", '(803) 470-9419', "Company 1", 'PO Box 23425',
'Columbia, SC 14550', 'jmony@gmail.com', 'Aaron, Rust. ', 'Fax (864) 751-5784', '1317 Waterfall, #2334', 'Orlando, FL 32804',
'amail@gmail.com', 'Betn, S. Raul', 'Fax (864) 666-4484', 'S. Raul Baron, P.A.', '1456 Edgewater Drive, #2034', 'Orlando, FL 32804',
'georgeamon@gmail.com', 'Abueno, Daniel George', '(444) 123-2633',
'3456 Robert Drive', '#2316', 'Charleston, SC 29492',
'oldmail@outlook.com']

我需要把这些数据整理成包含last_name、first_name、company、phone_number、fax_number、address、city、state、zip_code、email列的DataFrame,但遇到了问题:部分条目没有公司名称或传真号码,还有部分地址被拆分成了列表中的多个元素,现在卡住了。


解决方案

步骤1:分析数据规律

观察列表能发现,每个联系人的信息是从姓名(格式为Last, First)开始,到邮箱(带@)结束的连续条目。我们可以先把整个列表按联系人分组,再逐个解析每组内容。

步骤2:用正则匹配各类字段

先定义正则表达式来识别不同类型的字段:

  • 姓名:匹配xxx, xxx格式
  • 电话:匹配(xxx) xxx-xxxx格式
  • 传真:匹配以Fax开头的行
  • 邮箱:匹配带@的字符串
  • 城市/州/邮编:匹配City, State Zip格式

步骤3:分组并解析每个联系人

遍历列表,把每个联系人的信息单独分组,然后逐个提取字段,处理地址拼接、字段拆分。

完整代码实现

import pandas as pd
import re

# 定义正则表达式
name_pattern = re.compile(r'^[\w\s]+, [\w\s.]+$')  # 匹配Last, First格式
phone_pattern = re.compile(r'^\(\d{3}\) \d{3}-\d{4}$')  # 匹配(xxx) xxx-xxxx
fax_pattern = re.compile(r'^Fax \(\d{3}\) \d{3}-\d{4}$')  # 匹配Fax开头的传真
email_pattern = re.compile(r'^[\w.-]+@[\w.-]+$')  # 匹配邮箱
city_state_zip_pattern = re.compile(r'^([\w\s]+), ([A-Z]{2}) (\d{5})$')  # 匹配City, State Zip

# 把contentlist按联系人分组
contacts = []
current_contact = []

for item in contentlist:
    item = item.strip()  # 去除首尾空格
    # 遇到姓名且当前组不为空时,先把之前的组存入contacts
    if name_pattern.match(item) and current_contact:
        contacts.append(current_contact)
        current_contact = [item]
    elif name_pattern.match(item):
        current_contact = [item]
    else:
        current_contact.append(item)
# 加入最后一个联系人
if current_contact:
    contacts.append(current_contact)

# 解析每个联系人组,生成结构化数据
structured_data = []
for contact in contacts:
    data = {
        'last_name': '',
        'first_name': '',
        'company': '',
        'phone_number': '',
        'fax_number': '',
        'address': '',
        'city': '',
        'state': '',
        'zip_code': '',
        'email': ''
    }
    
    # 提取姓名
    name = contact[0].split(',')
    data['last_name'] = name[0].strip()
    data['first_name'] = name[1].strip().replace('.', '')  # 去掉末尾的点
    
    # 遍历剩余元素
    address_lines = []
    for item in contact[1:]:
        if phone_pattern.match(item):
            data['phone_number'] = item
        elif fax_pattern.match(item):
            data['fax_number'] = item.replace('Fax ', '')  # 去掉Fax前缀
        elif email_pattern.match(item):
            data['email'] = item
        elif city_state_zip_pattern.match(item):
            # 拆分城市、州、邮编
            match = city_state_zip_pattern.match(item)
            data['city'] = match.group(1)
            data['state'] = match.group(2)
            data['zip_code'] = match.group(3)
        else:
            # 剩下的就是公司或地址行,先判断是否是公司(如果还没填公司的话)
            if not data['company']:
                # 假设公司名称不是数字开头,就认为是公司(可根据实际调整)
                if not item[0].isdigit():
                    data['company'] = item
                else:
                    address_lines.append(item)
            else:
                address_lines.append(item)
    
    # 拼接地址行
    data['address'] = ', '.join(address_lines)
    structured_data.append(data)

# 转成DataFrame
df = pd.DataFrame(structured_data)
print(df)

代码说明

  • 分组逻辑:通过识别姓名开头和邮箱结尾,把每个联系人的信息单独分组。
  • 字段匹配:用正则精准识别各类字段,避免误判。
  • 地址处理:把分散的地址行拼接成完整地址,同时拆分城市、州、邮编。
  • 兼容缺失字段:如果某个字段不存在(比如没有公司或传真),会保留空值,不影响DataFrame构建。

内容的提问来源于stack exchange,提问作者Peter Languilla

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 09:55:26