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.2.tar.gz (17.3 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.2-py3-none-any.whl (18.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: pdf2text_arabic-0.1.2.tar.gz
  • Upload date:
  • Size: 17.3 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.2.tar.gz
Algorithm Hash digest
SHA256 aa9f6e1238e2cff96f6dfd210b8ca132eb6d56cec5b3348bd5d9a8d2d7c920e8
MD5 139156cd56376d708b33b53173496912
BLAKE2b-256 e87e45f6b135e87e0077d644b6124f8602db4cb810a12c5fea8bbdd281d1177d

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pdf2text_arabic-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 5658abc030a2b0f442f0adbdb7dcf7fa2d19e76f7e123ab8e1b04306705114c3
MD5 a85902177dad043cb0b9c3eab57afca4
BLAKE2b-256 1e1a44e71d926c873de38942c767f5433f1e3d33d9b9601d294284645feed73d

See more details on using hashes here.

Provenance

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