Skip to main content

Arabic PDF text extraction with ligature and RTL fixes

Project description

PDF2Text-Arabic

Arabic PDF text extraction built on PyMuPDF. Fixes ligature decomposition, RTL ordering, table extraction, and other issues that make raw PyMuPDF output unusable for Arabic.

What it fixes

# Problem Fix
1 Ligature decomposition — PyMuPDF breaks Arabic ligatures (الله, لأ, لإ) into LTR-ordered zero-width chars Detects zero-width clusters, reverses to RTL order
1b Lam-Alef swap — لا ligature decomposed as ال (alef before lam) Detects width ratio, swaps to correct order
2 Presentation Forms — Returns U+FB50–FDFF / U+FE70–FEFF instead of standard Arabic NFKC normalization
3 Line splitting — One visual line split into multiple rawdict lines at same y Y-coordinate merging with tolerance
4 Number reversal — RTL sorting reverses digit sequences (2019 → 9102) Detects LTR digit runs, reverses back
5 Arabic↔digit spacing — No space between Arabic text and numbers Regex-inserts spaces at boundaries
6 Artifact spaces — Space chars with overlapping bboxes cause false word breaks Only honors spaces with physical gaps > 0.5px
7 Invisible chars — Zero-width joiners, BOM, LTR/RTL marks, kashida Stripped in post-processing

Install

pip install pdf2text-arabic

From source:

pip install .
# or with uv
uv pip install .

Quick start

Python API

from pdf2text_arabic import extract_pdf, extract_page

# Extract entire PDF
text = extract_pdf("document.pdf")

# With cropping (remove headers/page numbers)
text = extract_pdf("document.pdf", crop_top=50, crop_bottom=30)

# Crop by percentage
text = extract_pdf("document.pdf", crop_top=5, crop_bottom=3, crop_unit="pct")

# Disable footnote separator detection
text = extract_pdf("document.pdf", detect_footer=False)

AI-friendly API (recommended for agents)

from pdf2text_arabic import extract_pdf_result, get_capabilities

caps = get_capabilities()
result = extract_pdf_result("document.pdf", on_empty="warn")

print(result.pages_total)
print(result.pages_with_text)
print(result.empty_pages)
print(result.warnings)
print(result.text)

Agent contract:

  • Prefer extract_pdf_result() over parsing logs.
  • Do not manually reorder Arabic text after extraction.
  • Use get_capabilities() before enabling OCR-specific behavior.

Single page

import fitz
from pdf2text_arabic import extract_page

doc = fitz.open("document.pdf")
text = extract_page(doc[0], crop_top=50, crop_bottom=30)
doc.close()

CLI

# Process all PDFs in a directory
pdf2text-arabic -i ./download -o ./output/plain_text

# Single file
pdf2text-arabic -f document.pdf -o ./output

# With cropping
pdf2text-arabic -i ./download --crop-top 50 --crop-bottom 30

# Crop by percentage, no footer detection
pdf2text-arabic -i ./download --crop-top 5 --crop-bottom 3 --crop-unit pct --no-footer

API reference

extract_pdf(pdf_path, **kwargs) → str

Extract text from all pages of a PDF.

Parameter Type Default Description
pdf_path str Path to the PDF file
crop_top float 0 Crop from top of each page
crop_bottom float 0 Crop from bottom of each page
crop_unit "px" | "pct" "px" Unit: points or percentage of page height
detect_footer bool True Auto-detect footnote separator lines and exclude content below

extract_page(page, **kwargs) → str

Extract text from a single fitz.Page. Same parameters as extract_pdf (except pdf_path).

extract_pdf_result(pdf_path, **kwargs) → ExtractionResult

Structured output for AI/automation:

  • text: final extracted text
  • pages_total: total page count
  • pages_with_text: number of non-empty extracted pages
  • empty_pages: list of page numbers that produced empty output
  • warnings: machine-readable warning tokens (example: empty_page:3)

Features

Table extraction

Tables are automatically detected via PyMuPDF's find_tables(), extracted with proper Arabic cell ordering, and formatted as pipe-delimited text. Merged cells are filled down so every row is self-contained:

الجهات | عدد المقاعد | مقر الدائرة الانتخابية
طنجة – تطوان – الحسيمة | 2 | ولاية جهة فاس - مكناس
الشرق | 2 | ولاية جهة فاس - مكناس
فاس - مكناس | 2 | ولاية جهة فاس - مكناس

Footer detection

Automatically detects horizontal separator lines (both vector drawings and text-based dashes) in the bottom 40% of each page and excludes footnote text below them. Handles non-selectable drawn lines and selectable ------ text.

Page cropping

Crop headers and page numbers by fixed pixel amount or percentage of page height.

Project structure

pdf2text_arabic/
├── __init__.py    # Public API: extract_pdf, extract_page
├── _chars.py      # Character-level ligature/overlap fixes
├── _text.py       # RTL text building, cleaning, line merging
├── _tables.py     # Table detection and formatting
├── _footer.py     # Footer separator detection
├── _extract.py    # Page/PDF extraction orchestration
└── cli.py         # CLI entry point

Integration with other projects

pip install pdf2text-arabic
from pdf2text_arabic import extract_pdf

def extract_law_text(path: str) -> str:
    return extract_pdf(path, crop_top=50, crop_bottom=30, detect_footer=True)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pdf2text_arabic-0.1.3.tar.gz (17.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pdf2text_arabic-0.1.3-py3-none-any.whl (18.4 kB view details)

Uploaded Python 3

File details

Details for the file pdf2text_arabic-0.1.3.tar.gz.

File metadata

  • Download URL: pdf2text_arabic-0.1.3.tar.gz
  • Upload date:
  • Size: 17.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pdf2text_arabic-0.1.3.tar.gz
Algorithm Hash digest
SHA256 b59e232010b41366d781650034962037b1ee7f5649069740f970325899674339
MD5 5389d97628a0da85edee1f7cde356fac
BLAKE2b-256 2229e1db7cccd9f740c6032fa000384b4deb52a52e9a0a729f6f5d527b5b6f7a

See more details on using hashes here.

Provenance

The following attestation bundles were made for pdf2text_arabic-0.1.3.tar.gz:

Publisher: publish.yml on crazytajdine/PDF2Text-Arabic

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pdf2text_arabic-0.1.3-py3-none-any.whl.

File metadata

File hashes

Hashes for pdf2text_arabic-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 e862e579b51098568bbd0a87922e75c563a68e6e1dd3ac0ec1d6b3a106efdade
MD5 45c8a8dc6f444c619a9d08766f8b41a6
BLAKE2b-256 51b57395e11d63bfcfe0372a9139f1f60f21924451341c369460ca813e084200

See more details on using hashes here.

Provenance

The following attestation bundles were made for pdf2text_arabic-0.1.3-py3-none-any.whl:

Publisher: publish.yml on crazytajdine/PDF2Text-Arabic

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page