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.5.tar.gz (17.7 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.5-py3-none-any.whl (19.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: pdf2text_arabic-0.1.5.tar.gz
  • Upload date:
  • Size: 17.7 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.5.tar.gz
Algorithm Hash digest
SHA256 a537601680688fb428118aed6bf7fa8db49f762e9c9ce9b834a5d6d329cfe308
MD5 55706d71dedc272f46e8cd3f3620cd0e
BLAKE2b-256 f1c564077871e958cac71e0349baead477e3154dc9838616210849ff1b751301

See more details on using hashes here.

Provenance

The following attestation bundles were made for pdf2text_arabic-0.1.5.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.5-py3-none-any.whl.

File metadata

File hashes

Hashes for pdf2text_arabic-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 56e7ab575117f83ce5633ef68a1cac491378b5aac1bbdb03e84c1bbf5e515cb2
MD5 3f7da50a2bbe15d1707b521588b4b0ff
BLAKE2b-256 6ca8fac4ddc5a5f942b9227b9d8122b054364388498f72862a336574a59ca4cb

See more details on using hashes here.

Provenance

The following attestation bundles were made for pdf2text_arabic-0.1.5-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