0Pricing
AI Agents · درس

تحليل PDF باستخدام PyMuPDF وpdfplumber

استخراج النصوص والجداول والبيانات الوصفية من ملفات PDF برمجيًا

تحليل PDF باستخدام PyMuPDF وpdfplumber درس مجاني في AI Agents على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في AI Agents، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة AI Agents 4 دروس في المجموع.

لماذا لا تُعدّ معالجة PDF أمرًا بسيطًا؟

ملفات PDF صيغة للعرض وليست صيغة للبيانات. يُخزَّن النص على شكل محارف موضوعة في مواقع محددة، لا على شكل فقرات منطقية. ويتطلب استخراج نص ذي معنى فهم التخطيط، وترتيب القراءة، وخصائص الخط، والتعامل مع حالات خاصة مثل التخطيطات متعددة الأعمدة، والرؤوس والتذييلات، والصور المضمّنة.

تسود مكتبتان في هذا المجال: PyMuPDF (للسرعة) وpdfplumber (لاستخراج الجداول).

أساسيات PyMuPDF

PyMuPDF (ويُستورد باسم fitz) أسرع مكتبة Python لمعالجة ملفات PDF. وهي تتعامل مع استخراج النصوص، والبيانات الوصفية، والصور، والعرض. ثبّتها باستخدام 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 وpdfplumber

استخدم PyMuPDF لاستخراج النص لأنه أسرع، واستخدم pdfplumber لاكتشاف الجداول لأنه أكثر دقة. يشغّل المستخرج المدمج المكتبتين على كل صفحة، ثم يعيد محتوى منظمًا يفصل بين النصوص والجداول.

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، احفظه بتنسيق يمكن للوكلاء اللاحقين استهلاكه. تعمل الملفات النصية العادية جيدًا مع مسارات التضمين، بينما يحافظ JSON على بنية الصفحات لتتبع الاستشهادات.

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', '.')

اختبار المعرفة

ما مكتبة Python الأنسب لاستخراج الجداول من ملفات PDF؟

مراجعة: تحليل PDF باستخدام PyMuPDF وpdfplumber

يُعد PyMuPDF (fitz) الخيار السريع لاستخراج النص والبيانات الوصفية والتعامل مع التخطيطات متعددة الأعمدة. وتتفوق pdfplumber في استخراج الجداول باستخدام استراتيجيات هندسية قابلة للتهيئة.

تشمل التقنيات الأساسية: استخدام get_text('blocks') للاستخراج مع مراعاة المواضع، وتصفيـة الرؤوس والتذييلات وفق موضعها الرأسي، والتعامل مع التخطيطات متعددة الأعمدة بترتيب الكتل حسب العمود، وتقسيم النص إلى مقاطع متداخلة لاستخدامها في أنظمة استرجاع الوكلاء. اجمع بين المكتبتين للحصول على أفضل النتائج.

الأسئلة الشائعة

هل درس «تحليل PDF باستخدام PyMuPDF وpdfplumber» مجاني؟

نعم — نص درس «تحليل PDF باستخدام PyMuPDF وpdfplumber» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة AI Agents، انتقل إلى CoddyKit PRO. تتضمن دورة AI Agents 4 دروس في المجموع.

ماذا ستتعلم في «تحليل PDF باستخدام PyMuPDF وpdfplumber»؟

استخراج النصوص والجداول والبيانات الوصفية من ملفات PDF برمجيًا تتمرن على AI Agents مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ AI Agents؟

لا تُشترط خبرة سابقة. AI Agents على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.

كم من الوقت يستغرق درس «تحليل PDF باستخدام PyMuPDF وpdfplumber»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس AI Agents هذا؟

نعم. كل درس في AI Agents يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. تحليل PDF باستخدام PyMuPDF وpdfplumber
  2. OCR للمستندات الممسوحة ضوئيًا
  3. وكلاء الأسئلة والأجوبة عبر مستندات متعددة
  4. تصنيف المستندات وتوجيهها
← العودة إلى AI Agents