Python把PDF表格完整轉(zhuǎn)換成Excel的小白教程
很多同學(xué)第一次接觸 PDF 數(shù)據(jù)處理時(shí),都會(huì)遇到一個(gè)問(wèn)題:
PDF 里的表格能看,不能算,不能統(tǒng)計(jì)。
比如:
- 招聘成績(jī)公示
- 學(xué)校成績(jī)單
- 名單匯總表
本文將通過(guò)一個(gè)完整可運(yùn)行的 Python 示例,一步一步教你:
如何把一個(gè)多頁(yè) PDF 表格,穩(wěn)定地轉(zhuǎn)換成 Excel 文件
一、整體思路先說(shuō)明(很重要)
在正式寫代碼前,你一定要明白一件事:
PDF ≠ Excel
- Excel:天然是“行 + 列”
- PDF:只是“排好版的頁(yè)面”
所以我們要做的是:
1. 從 PDF 中提取“表格結(jié)構(gòu)” 2. 把每一行數(shù)據(jù)收集起來(lái) 3. 修復(fù)列數(shù)不一致的問(wèn)題 4. 再導(dǎo)出為 Excel
二、完整代碼(先給結(jié)論)
下面是完整、可直接運(yùn)行的代碼,后面我會(huì)逐步拆解講解。
import pdfplumber
import pandas as pd
import os
def pdf_to_excel(pdf_path, excel_path):
all_rows = []
# 打開(kāi) PDF
with pdfplumber.open(pdf_path) as pdf:
print(f"PDF共有 {len(pdf.pages)} 頁(yè)")
# 遍歷每一頁(yè)
for page_num, page in enumerate(pdf.pages, start=1):
print(f"正在處理第 {page_num} 頁(yè)...")
tables = page.extract_tables()
if not tables:
continue
for table in tables:
for row in table:
# 跳過(guò)全空行
if row and any(cell and cell.strip() for cell in row if isinstance(cell, str)):
all_rows.append(row)
if not all_rows:
print(" 未提取到任何表格數(shù)據(jù)")
return
# 計(jì)算最大列數(shù)
max_cols = max(len(row) for row in all_rows)
print(f"檢測(cè)到最大列數(shù):{max_cols}")
# 統(tǒng)一所有行的列數(shù)
normalized_rows = []
for row in all_rows:
if len(row) < max_cols:
row = row + [None] * (max_cols - len(row))
elif len(row) > max_cols:
row = row[:max_cols]
normalized_rows.append(row)
# 第一行作為表頭
header = normalized_rows[0]
data = normalized_rows[1:]
# 去除重復(fù)表頭行
clean_data = []
for row in data:
if row != header:
clean_data.append(row)
# 構(gòu)建 DataFrame
df = pd.DataFrame(clean_data, columns=header)
# 清理空行、空列
df = df.dropna(how='all').dropna(axis=1, how='all')
# 導(dǎo)出 Excel
df.to_excel(excel_path, index=False, engine='openpyxl')
print("\n 轉(zhuǎn)換完成")
print(f"Excel 文件路徑:{excel_path}")
print(f"數(shù)據(jù)行數(shù):{len(df)}")
print(f"列數(shù):{len(df.columns)}")
print("列名:", list(df.columns))
print("\n前 5 行數(shù)據(jù)預(yù)覽:")
print(df.head())
if __name__ == "__main__":
pdf_file = "Example.pdf"
excel_file = "Result.xlsx"
if not os.path.exists(pdf_file):
print(f"找不到 PDF 文件:{pdf_file}")
else:
pdf_to_excel(pdf_file, excel_file)三、逐步解析代碼(小白重點(diǎn))
1、導(dǎo)入庫(kù)
import pdfplumber import pandas as pd import os
作用說(shuō)明:
| 庫(kù) | 作用 |
|---|---|
| pdfplumber | 讀取 PDF、提取表格 |
| pandas | 處理表格數(shù)據(jù) |
| os | 判斷文件是否存在 |
2、定義核心函數(shù)
def pdf_to_excel(pdf_path, excel_path):
這個(gè)函數(shù)只做一件事:
把一個(gè) PDF 表格文件,轉(zhuǎn)換成 Excel
3、收集所有表格行
all_rows = []
為什么要這樣做?
因?yàn)?PDF 是一頁(yè)一頁(yè)的,
但 Excel 是一個(gè)整體表格。
4、打開(kāi) PDF 并逐頁(yè)處理
with pdfplumber.open(pdf_path) as pdf:
pdf.pages:PDF 的每一頁(yè)extract_tables():提取當(dāng)前頁(yè)中的表格
5、跳過(guò)空行(非常關(guān)鍵)
if row and any(cell and cell.strip() for cell in row if isinstance(cell, str)):
作用:
- 防止空行進(jìn)入 Excel
- 防止生成一堆沒(méi)用的數(shù)據(jù)
6、為什么要“統(tǒng)一列數(shù)”(核心思想)
max_cols = max(len(row) for row in all_rows)
現(xiàn)實(shí)中的 PDF 表格:
- 有的頁(yè) 8 列
- 有的頁(yè) 9 列
- 有的頁(yè) 10 列
如果不統(tǒng)一,pandas 會(huì)直接報(bào)錯(cuò)
所以我們要:
不足的補(bǔ) None,多的截?cái)?
7、第一行作為表頭
header = normalized_rows[0]
PDF 表格通常每一頁(yè)都有表頭,
我們只保留第一行作為最終列名。
8、去掉重復(fù)表頭行
if row != header:
clean_data.append(row)
否則 Excel 會(huì)變成:
職位代碼 | 職位名稱 | ... 職位代碼 | 職位名稱 | ... 職位代碼 | 職位名稱 | ...
9、導(dǎo)出 Excel
df.to_excel(excel_path, index=False, engine='openpyxl')
這一步就是真正生成 Excel 文件。
四、示例 PDF 模板(示意)
假設(shè)你的 PDF 表格內(nèi)容長(zhǎng)這樣(每一頁(yè)類似):
| 職位代碼 | 職位名稱 | 準(zhǔn)考證號(hào) | 考場(chǎng)號(hào) | 座位號(hào) | 成績(jī) |
|---|---|---|---|---|---|
| 00001 | A001 | A00010201 | 2 | 1 | 78.25 |
| 00001 | A001 | A00010101 | 1 | 1 | 82.50 |
五、預(yù)期 Excel 處理結(jié)果
最終生成的 Excel 表格應(yīng)為:
| 職位代碼 | 職位名稱 | 準(zhǔn)考證號(hào) | 考場(chǎng)號(hào) | 座位號(hào) | 成績(jī) |
|---|---|---|---|---|---|
| 00001 | A001 | A00010201 | 2 | 1 | 78.25 |
| 00001 | A001 | A00010101 | 1 | 1 | 82.50 |
| … | … | … | … | … | … |
一人一行,可直接統(tǒng)計(jì)、排序、篩選
六、這個(gè)程序能做什么 / 不能做什么
能處理
- 多頁(yè) PDF 表格
- 列數(shù)不一致
- 招聘、公示、成績(jī)類 PDF
不能處理
- 掃描版 PDF(圖片)
- 完全靠空格排版的“假表格”
七、總結(jié)一句話
PDF → Excel 的難點(diǎn)不在“讀取”,而在“結(jié)構(gòu)修復(fù)”。
這份代碼已經(jīng)解決了:
- 多頁(yè)
- 表頭重復(fù)
- 列數(shù)不一致
以上就是Python把PDF表格完整轉(zhuǎn)換成Excel的小白教程的詳細(xì)內(nèi)容,更多關(guān)于Python PDF表格轉(zhuǎn)成Excel的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python 實(shí)現(xiàn)交換兩個(gè)列表元素的位置示例
今天小編就為大家分享一篇python 實(shí)現(xiàn)交換兩個(gè)列表元素的位置示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-06-06
使用Python繪制動(dòng)態(tài)愛(ài)心并表白的代碼詳解
在這個(gè)充滿浪漫的季節(jié),如何用代碼表達(dá)你的愛(ài)意呢?今天我們將使用 Python 的 matplotlib 和 numpy 庫(kù)繪制一個(gè)動(dòng)態(tài)的愛(ài)心,并且在愛(ài)心上添加表白的文字,這將是一個(gè)獨(dú)特而浪漫的方式來(lái)表達(dá)你的心聲,感興趣的小伙伴跟著小編來(lái)看看吧2025-04-04
python事件驅(qū)動(dòng)event實(shí)現(xiàn)詳解
這篇文章主要為大家詳細(xì)介紹了python事件驅(qū)動(dòng)event實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11
LangChain簡(jiǎn)化ChatGPT工程復(fù)雜度使用詳解
這篇文章主要為大家介紹了LangChain簡(jiǎn)化ChatGPT工程復(fù)雜度使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
numpy 對(duì)矩陣中Nan的處理:采用平均值的方法
今天小編就為大家分享一篇numpy 對(duì)矩陣中Nan的處理:采用平均值的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-10-10
python中b=a和b=a[:]區(qū)別小結(jié)
Python中b = a和b = a[:]有顯著區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2026-03-03
Python利用字典和列表實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Python如何利用字典和列表實(shí)現(xiàn)一個(gè)簡(jiǎn)易的學(xué)生信息管理系統(tǒng),文中詳細(xì)注釋,方便理解,需要的可以參考一下2022-06-06
Mac PyCharm中的.gitignore 安裝設(shè)置教程
這篇文章主要介紹了Mac PyCharm中的.gitignore 安裝設(shè)置教程,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04

