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

将PDF多列名单转换为DataFrame的Python代码报错求助

问题描述

需要处理PDF第13-15页的名单:其中第13、14页为3列式布局,第15页为2列式布局,最终要整理成带有指定列名的DataFrame。

第13页第一列的示例内容如下:

AUVERGNE-RHÔNE-ALPES
24
01. AIN | 1 | Malafretaz Plage principale
03. ALLIER | 1 | Vieure Plage du plan d’eau
de Vieure
07. ARDÈCHE| 1 |Saint-Martin-d’Ardèche
Plage du Grain de sel
15. CANTAL | 1 | Trémouille Lastioulles

理想的CSV输出格式为:

region,region_code,dpt_code,departement,flag,commune,plage
AUVERGNE-RHÔNE-ALPES,24,01.,AIN,| 1 |,Malafretaz,Plage principale
 , ,03.,ALLIER,| 1 |,Vieure,Plage du plan d’eau de Vieure
 , ,07.,ARDÈCHE,| 1 |,Saint-Martin-d’Ardèche,Plage du Grain de sel
 , ,15.,CANTAL,| 1 |,Trémouille,Lastioulles

尝试了以下Python代码,但在列整理步骤中出错,寻求解决方法:

import tabula
import pandas as pd

# Link to PDF
pdf_url = "https://www.teragir.org/wp-content/uploads/2023/05/DP-PAVBLEU-2023-WEB.pdf"

# Use Tabula to extrat the data on page 13 (I start with one single page)
df = tabula.read_pdf(pdf_url, pages=13)[0]

# Delete empty lines
df.dropna(inplace=True)

# Organize the columns
df.columns = ["Region", "Region_N", "Dpt_N", "Departement", "Flag", "Commune", "Plage"]

# Fill the missing values in the columns "Region" et "Region_N"
df["Region"].fillna(method="ffill", inplace=True)
df["Region_N"].fillna(method="ffill", inplace=True)

# Save the table in a CSV
df.to_csv("liste_plages.csv", index=False)
解决方案

问题核心在于Tabula默认提取的列结构不符合预期,且存在跨行文本拆分(比如“Plage du plan d’eau de Vieure”分两行显示),需要调整提取策略并手动处理文本分割。

完整解决代码

import tabula
import pandas as pd
import re

pdf_url = "https://www.teragir.org/wp-content/uploads/2023/05/DP-PAVBLEU-2023-WEB.pdf"

def process_page(page_num, is_three_cols=True):
    # 根据页面列布局定义分隔位置(可根据实际PDF微调)
    columns = [100, 300, 500, 700] if is_three_cols else [100, 400]
    
    # 以流式模式提取页面数据,准确定位列分隔
    df = tabula.read_pdf(
        pdf_url,
        pages=page_num,
        stream=True,
        columns=columns,
        pandas_options={'header': None}
    )[0]
    
    # 合并所有列的文本,处理跨行拆分的内容
    df['combined'] = df.apply(
        lambda row: ' '.join([str(cell) for cell in row if pd.notna(cell)]),
        axis=1
    )
    df = df[['combined']].dropna()
    
    result = []
    current_region = None
    current_region_code = None
    
    for line in df['combined']:
        line = line.strip()
        if not line:
            continue
        
        # 匹配区域名称(纯字母/空格/连字符组成)
        if re.match(r'^[A-ZÀ-ÿ\s-]+$', line):
            current_region = line
            continue
        # 匹配区域代码(纯数字)
        elif line.isdigit():
            current_region_code = line
            continue
        # 处理数据行(包含|分隔符)
        elif '|' in line:
            # 提取flag部分
            flag_part = re.search(r'\|\s*\d+\s\|', line).group()
            left_segment = line.split(flag_part)[0].strip()
            right_segment = line.split(flag_part)[1].strip()
            
            # 拆分省份代码和名称
            dpt_match = re.match(r'^(\d+\.)\s*(.*)', left_segment)
            dpt_code = dpt_match.group(1) if dpt_match else ''
            departement = dpt_match.group(2).strip() if dpt_match else left_segment
            
            # 拆分市镇和沙滩名称
            parts = right_segment.split(' ', 1)
            commune = parts[0].strip()
            plage = parts[1].strip() if len(parts) >=2 else ''
            
            result.append({
                'region': current_region,
                'region_code': current_region_code,
                'dpt_code': dpt_code,
                'departement': departement,
                'flag': flag_part,
                'commune': commune,
                'plage': plage
            })
    
    return pd.DataFrame(result)

# 分别处理3列布局的13、14页和2列布局的15页
df_13 = process_page(13)
df_14 = process_page(14)
df_15 = process_page(15, is_three_cols=False)

# 合并所有页面数据并填充缺失的区域信息
final_df = pd.concat([df_13, df_14, df_15], ignore_index=True)
final_df['region'] = final_df['region'].ffill()
final_df['region_code'] = final_df['region_code'].ffill()

# 保存为CSV
final_df.to_csv("liste_plages.csv", index=False)

代码说明

  1. process_page函数:根据页面列数调整提取参数,合并跨行文本,通过正则匹配拆分出目标字段。
  2. 跨行文本处理:将拆分到下一行的沙滩名称合并回对应数据行,避免信息断裂。
  3. 正则匹配:精准识别区域名称、区域代码和数据行结构,确保各字段拆分准确。
  4. 向前填充:对后续行的区域名称和代码进行填充,保证数据完整性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 13:28:10