การแยกวิเคราะห์ PDF ด้วย PyMuPDF และ pdfplumber
ดึงข้อความ ตาราง และข้อมูลกำกับจาก PDF ด้วยโปรแกรม
การแยกวิเคราะห์ PDF ด้วย PyMuPDF และ pdfplumber เป็นบทเรียน AI Agents ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Agents และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน
เหตุใดการแยกวิเคราะห์ PDF จึงไม่ใช่เรื่องง่าย
PDF เป็นรูปแบบการนำเสนอ ไม่ใช่รูปแบบข้อมูล ข้อความถูกจัดเก็บเป็นอักขระภาพที่วางตามตำแหน่ง ไม่ใช่ย่อหน้าตามตรรกะ การแยกข้อความที่มีความหมายจึงต้องเข้าใจการจัดวาง ลำดับการอ่าน คุณสมบัติของแบบอักษร และจัดการกรณีต่าง ๆ เช่น การจัดวางหลายคอลัมน์ หัวกระดาษ/ท้ายกระดาษ และรูปภาพที่ฝังอยู่
มีไลบรารีหลักที่ใช้กันอย่างแพร่หลายสองรายการ ได้แก่ PyMuPDF (ความเร็ว) และ pdfplumber (การแยกตาราง)
พื้นฐาน PyMuPDF
PyMuPDF (นำเข้าในชื่อ fitz) เป็นไลบรารี PDF สำหรับ Python ที่เร็วที่สุด รองรับการแยกข้อความ ข้อมูลเมตา รูปภาพ และการเรนเดอร์ ติดตั้งด้วย pip install pymupdf
import fitz # PyMuPDF
# Open a PDF
doc = fitz.open('document.pdf')
print(f'Pages: {len(doc)}')
print(f'Metadata: {doc.metadata}')
# Extract text from all pages
full_text = ''
for page_num in range(len(doc)):
page = doc[page_num]
text = page.get_text() # plain text extraction
full_text += f'--- Page {page_num + 1} ---\n{text}\n'
doc.close()
print(full_text[:500])โหมดการแยกข้อความของ PyMuPDF
page.get_text() รองรับรูปแบบผลลัพธ์หลายแบบ ใช้ 'text' สำหรับข้อความธรรมดา ใช้ 'blocks' สำหรับบล็อกข้อความพร้อมกรอบขอบเขต และใช้ 'dict' สำหรับผลลัพธ์แบบมีโครงสร้างที่ละเอียด ซึ่งรวมชื่อและขนาดแบบอักษรไว้ด้วย
import fitz
doc = fitz.open('report.pdf')
page = doc[0]
# Mode 1: plain text
plain = page.get_text('text')
# Mode 2: blocks (each block has bbox + text)
blocks = page.get_text('blocks')
for block in blocks:
x0, y0, x1, y1, text, block_no, block_type = block
if block_type == 0: # text block (1 = image)
print(f'Block at ({x0:.0f},{y0:.0f}): {text[:80]}')
# Mode 3: dict (full detail including font info)
page_dict = page.get_text('dict')
for block in page_dict['blocks']:
if block.get('type') == 0: # text
for line in block['lines']:
for span in line['spans']:
print(f"Font: {span['font']}, Size: {span['size']:.1f}, Text: {span['text']}")
doc.close()การแยกข้อมูลเมตาของหน้า
ข้อมูลเมตาของหน้าช่วยให้เอเจนต์เข้าใจโครงสร้างเอกสาร ได้แก่ จำนวนหน้า ชื่อเอกสาร ผู้เขียน วันที่สร้าง และขนาดหน้า PyMuPDF เปิดให้เข้าถึงข้อมูลทั้งหมดนี้ได้
import fitz
def extract_pdf_metadata(filepath):
doc = fitz.open(filepath)
meta = doc.metadata
info = {
'title': meta.get('title', 'Unknown'),
'author': meta.get('author', 'Unknown'),
'subject': meta.get('subject', ''),
'creator': meta.get('creator', ''),
'created': meta.get('creationDate', ''),
'modified': meta.get('modDate', ''),
'pages': len(doc),
'page_size': {
'width': doc[0].rect.width,
'height': doc[0].rect.height
}
}
doc.close()
return info
meta = extract_pdf_metadata('contract.pdf')
print(f"Title: {meta['title']}, Pages: {meta['pages']}")การใช้ pdfplumber เพื่อแยกตาราง
pdfplumber มีความสามารถโดดเด่นในการแยกตารางจาก PDF โดยใช้การวิเคราะห์ทางเรขาคณิตเพื่อตรวจจับขอบเขตเซลล์ แม้ใน PDF ที่ไม่มีการกำกับตารางไว้อย่างชัดเจน
ติดตั้งด้วย pip install pdfplumber
import pdfplumber
with pdfplumber.open('financial_report.pdf') as pdf:
for page_num, page in enumerate(pdf.pages):
tables = page.extract_tables()
for table_idx, table in enumerate(tables):
print(f'Page {page_num+1}, Table {table_idx+1}:')
# table is a list of rows; each row is a list of cell strings
headers = table[0]
for row in table[1:]:
row_dict = dict(zip(headers, row))
print(row_dict)การตั้งค่าตารางของ pdfplumber
การแยกตารางของ pdfplumber สามารถปรับแต่งด้วยการตั้งค่าเพื่อรองรับรูปแบบตารางต่าง ๆ เช่น เส้นตารางที่กำหนดไว้อย่างชัดเจน คอลัมน์ที่คั่นด้วยช่องว่าง หรือการจัดวางแบบผสม
import pdfplumber
# Custom table settings for borderless tables
table_settings = {
'vertical_strategy': 'text', # 'lines', 'lines_strict', 'text', 'explicit'
'horizontal_strategy': 'text',
'snap_tolerance': 5,
'join_tolerance': 3,
'edge_min_length': 50,
'min_words_vertical': 3,
'min_words_horizontal': 1
}
with pdfplumber.open('nolines_table.pdf') as pdf:
page = pdf.pages[0]
table = page.extract_table(table_settings)
if table:
import csv
import io
output = io.StringIO()
writer = csv.writer(output)
writer.writerows(table)
csv_string = output.getvalue()
print(csv_string[:300])การจัดการรูปแบบหลายคอลัมน์
บทความวิชาการและหนังสือพิมพ์ใช้การจัดวางแบบหลายคอลัมน์ การแยกข้อความแบบพื้นฐานจะอ่านข้ามคอลัมน์จากซ้ายไปขวา ทำให้ได้ข้อความที่สับสน แก้ไขโดยจัดเรียงบล็อกข้อความตามคอลัมน์ก่อน
import fitz
def extract_multicolumn_text(page, n_columns=2):
page_width = page.rect.width
col_width = page_width / n_columns
blocks = page.get_text('blocks')
# Filter text blocks only
text_blocks = [b for b in blocks if b[6] == 0]
# Assign each block to a column based on x position
columns = [[] for _ in range(n_columns)]
for block in text_blocks:
x0 = block[0]
col_idx = min(int(x0 / col_width), n_columns - 1)
columns[col_idx].append(block)
# Sort each column by vertical position
for col in columns:
col.sort(key=lambda b: b[1]) # sort by y0
# Read columns left to right
full_text = ''
for col in columns:
for block in col:
full_text += block[4] + '\n'
return full_textการกรองหัวกระดาษและท้ายกระดาษ
หัวกระดาษและท้ายกระดาษของ PDF จะปรากฏซ้ำในทุกหน้าและทำให้ข้อความที่แยกออกมาปะปน ควรระบุด้วยตำแหน่งแนวตั้ง (10% ด้านบนหรือด้านล่างของหน้า) แล้วไม่นำสิ่งเหล่านี้ไปรวมในการแยกเนื้อหา
import fitz
def extract_without_headers_footers(page, margin_ratio=0.08):
page_height = page.rect.height
top_margin = page_height * margin_ratio
bottom_margin = page_height * (1 - margin_ratio)
blocks = page.get_text('blocks')
content_blocks = []
for block in blocks:
x0, y0, x1, y1, text, block_no, block_type = block
if block_type != 0:
continue # skip image blocks
# Skip blocks in header or footer zone
if y0 < top_margin or y1 > bottom_margin:
continue
content_blocks.append(text)
return '\n'.join(content_blocks)การแบ่งข้อความ PDF เป็นชิ้นสำหรับเอเจนต์
PDF ขนาดยาวต้องแบ่งออกเป็นชิ้นสำหรับการทำเอ็มเบดดิงและการค้นคืน ควรแบ่งตรงขอบเขตตามธรรมชาติ เช่น ย่อหน้า ส่วน หรือหน้า และให้ชิ้นต่าง ๆ มีเนื้อหาซ้อนทับกัน เพื่อไม่ให้บริบทถูกตัดขาดกลางประโยค
import fitz
def pdf_to_chunks(filepath, chunk_size=1000, overlap=200):
doc = fitz.open(filepath)
chunks = []
for page_num in range(len(doc)):
page = doc[page_num]
page_text = page.get_text()
# Split into chunks with overlap
start = 0
while start < len(page_text):
end = start + chunk_size
chunk = page_text[start:end]
chunks.append({
'text': chunk,
'page': page_num + 1,
'char_start': start,
'source': filepath
})
start += chunk_size - overlap # overlap
doc.close()
return chunks
chunks = pdf_to_chunks('research_paper.pdf')
print(f'Total chunks: {len(chunks)}')
print(f'Sample: {chunks[0]["text"][:200]}')การผสาน PyMuPDF กับพีดีเอฟพลัมเบอร์
ใช้ PyMuPDF สำหรับการแยกข้อความ (เร็วกว่า) และพีดีเอฟพลัมเบอร์สำหรับการตรวจจับตาราง (แม่นยำกว่า) ตัวแยกข้อมูลแบบผสานจะทำงานทั้งสองอย่างในแต่ละหน้า แล้วส่งคืนเนื้อหาแบบมีโครงสร้าง โดยแยกข้อความกับตารางออกจากกัน
import fitz
import pdfplumber
def full_pdf_extract(filepath):
result = {'text_by_page': [], 'tables': []}
# Text extraction with PyMuPDF
doc = fitz.open(filepath)
for i in range(len(doc)):
text = extract_without_headers_footers(doc[i])
result['text_by_page'].append({'page': i + 1, 'text': text})
doc.close()
# Table extraction with pdfplumber
with pdfplumber.open(filepath) as pdf:
for page_num, page in enumerate(pdf.pages):
tables = page.extract_tables()
for t in tables:
result['tables'].append({
'page': page_num + 1,
'headers': t[0] if t else [],
'rows': t[1:] if t and len(t) > 1 else []
})
return resultการบันทึกข้อความที่แยกแล้วลงไฟล์
หลังจากแยกข้อความจาก PDF แล้ว ให้บันทึกในรูปแบบที่เอเจนต์ขั้นถัดไปสามารถใช้งานได้ ไฟล์ข้อความธรรมดาเหมาะสำหรับกระบวนการทำเอ็มเบดดิง ส่วนข้อมูลแบบมีโครงสร้างจะรักษาโครงสร้างของหน้าไว้เพื่อการติดตามแหล่งอ้างอิง
import json, os
class FakePage:
def __init__(self, text): self.text = text
def get_text(self): return self.text
class FakeDoc(list):
def close(self): pass
def fitz_open(path):
return FakeDoc([FakePage('Page 1 text'), FakePage('Page 2 text')])
def pdf_to_text_file(pdf_path, output_dir):
doc = fitz_open(pdf_path)
base = os.path.splitext(os.path.basename(pdf_path))[0]
txt_path = os.path.join(output_dir, base + '.txt')
with open(txt_path, 'w', encoding='utf-8') as f:
for i, page in enumerate(doc):
f.write(f'--- Page {i+1} ---\n{page.get_text()}\n')
json_path = os.path.join(output_dir, base + '.json')
pages = [{'page': i+1, 'text': p.get_text()} for i, p in enumerate(doc)]
with open(json_path, 'w') as f:
json.dump({'source': pdf_path, 'pages': pages}, f, indent=2)
doc.close()
print(f'Saved: {txt_path} and {json_path}')
return txt_path, json_path
pdf_to_text_file('sample.pdf', '.')ตรวจสอบความรู้
ไลบรารีไพธอนใดเหมาะที่สุดสำหรับการแยกตารางจากไฟล์ PDF
ทบทวน: การแยกวิเคราะห์ PDF ด้วย PyMuPDF และพีดีเอฟพลัมเบอร์
PyMuPDF (fitz) เป็นตัวเลือกที่รวดเร็วสำหรับการแยกข้อความ ข้อมูลเมทาดาทา และการจัดการเค้าโครงแบบหลายคอลัมน์ ส่วน พีดีเอฟพลัมเบอร์โดดเด่นด้านการแยกตารางด้วยกลยุทธ์เชิงเรขาคณิตที่กำหนดค่าได้
เทคนิคสำคัญ ได้แก่ ใช้ get_text('blocks') สำหรับการแยกข้อมูลที่คำนึงถึงตำแหน่ง กรองส่วนหัวและท้ายกระดาษตามตำแหน่งแนวตั้ง จัดการเค้าโครงหลายคอลัมน์ด้วยการเรียงบล็อกตามคอลัมน์ และแบ่งข้อความเป็นชิ้นที่มีส่วนซ้อนทับกันสำหรับระบบค้นคืนของเอเจนต์ ควรใช้ทั้งสองไลบรารีร่วมกันเพื่อให้ได้ผลลัพธ์ที่ดีที่สุด
คำถามที่พบบ่อย
บทเรียน “การแยกวิเคราะห์ PDF ด้วย PyMuPDF และ pdfplumber” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การแยกวิเคราะห์ PDF ด้วย PyMuPDF และ pdfplumber” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Agents ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การแยกวิเคราะห์ PDF ด้วย PyMuPDF และ pdfplumber”
ดึงข้อความ ตาราง และข้อมูลกำกับจาก PDF ด้วยโปรแกรม คุณปฏิบัติ AI Agents ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Agents หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Agents บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “การแยกวิเคราะห์ PDF ด้วย PyMuPDF และ pdfplumber” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน AI Agents นี้ได้ไหม
ได้ บทเรียน AI Agents ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การแยกวิเคราะห์ PDF ด้วย PyMuPDF และ pdfplumber
- OCR สำหรับเอกสารสแกน
- ตัวแทนถามตอบจากเอกสารหลายฉบับ
- การจำแนกและกำหนดเส้นทางเอกสาร