Batch OCR tool for scanned PDFs using PDF Expert on macOS. Converts image-based PDFs into searchable documents while never modifying the original files.
通过 macOS 上的 PDF Expert 批量 OCR 扫描版 PDF,生成可搜索的新文件。原文件始终不受影响。
- Three-phase pipeline / 三阶段流水线:Pre-scan → Batch OCR → Post-validation
- Breakpoint resume / 断点续传:SQLite-based progress tracking, safe to interrupt and resume
- Error isolation / 错误隔离:Single file failure does not abort the entire batch
- Memory management / 内存管理:Auto-restart PDF Expert every N files to prevent memory bloat
- Safe interrupt / 安全中断:Ctrl+C saves progress before exit
- Large file support / 大文件支持:Automatic splitting for PDFs > 100 pages
- Text layer verification / 文字层验证:PyMuPDF validates OCR actually produced searchable text
| Component | Version |
|---|---|
| macOS | 14+ (AppleScript UI Scripting required) |
| Python | 3.11+ |
| PDF Expert | 3.x (Chinese UI / 中文界面) |
| PyMuPDF | >= 1.23.0 |
Important: PDF Expert must be the default PDF application and must have OCR language configured (default: Chinese / 中文).
# Install Python dependency
pip install -r requirements.txt
# Or using uv
uv pip install -r requirements.txtDetect which PDFs already have a text layer to avoid redundant OCR.
python scan_pdfs.py /path/to/your/pdfs --output scan_result.jsonOutput:
scan_result.json— Full scan reportocr_queue.json— Queue file for Phase 1 (auto-generated)
Status codes:
| Status | Meaning |
|---|---|
need_ocr |
Scanned PDF, requires OCR |
has_text |
Already searchable, skipped |
hand_drawn |
Hand-drawn / vector-heavy, skipped |
error |
Failed to open/read |
Drive PDF Expert via AppleScript to process files one by one.
python batch_ocr.py \
--queue ocr_queue.json \
--output-dir ./output \
--db progress.db \
--scpt pdfexpert_ocr.scptBehavior:
- Creates a copy (
*_OCR.pdf) inoutput-dirbefore processing - Original files are never touched
- Automatically restarts PDF Expert every 10 files (configurable)
- Progress saved to SQLite database — re-run to resume from interruption
Single file mode (for testing):
osascript pdfexpert_ocr.scpt /path/to/file.pdfRandom sampling to verify OCR quality.
python validate_ocr.py --db progress.dbFor PDFs > 100 pages, split into chunks before OCR to avoid memory/timeouts:
import fitz
from pathlib import Path
src = "large_400pages.pdf"
out_dir = Path("./chunks")
out_dir.mkdir(exist_ok=True)
doc = fitz.open(src)
chunk_size = 50
for start in range(0, len(doc), chunk_size):
end = min(start + chunk_size, len(doc))
chunk = fitz.open()
chunk.insert_pdf(doc, from_page=start, to_page=end - 1)
chunk.save(out_dir / f"part_{start+1:03d}-{end:03d}.pdf")
chunk.close()
doc.close()Then run Phase 1 on the chunks and merge afterward.
Edit config.json:
{
"phase0": {
"threshold": 20,
"recursive": false
},
"phase1": {
"output_suffix": "_OCR",
"ocr_language": "中文",
"restart_interval": 10,
"single_timeout_seconds": 300,
"delay_between_files": 0.5
},
"phase2": {
"sample_rate": 0.05,
"min_sample": 10,
"validation_threshold": 20
}
}| Key | Description | Default |
|---|---|---|
phase0.threshold |
Character threshold for text layer detection | 20 |
phase0.recursive |
Recursively scan subdirectories | false |
phase1.output_suffix |
Suffix for OCR output files | _OCR |
phase1.ocr_language |
OCR language setting in PDF Expert | 中文 |
phase1.restart_interval |
Restart PDF Expert every N files | 10 |
phase1.single_timeout_seconds |
Per-file timeout | 300 |
phase2.sample_rate |
Validation sampling rate | 0.05 |
phase2.min_sample |
Minimum validation samples | 10 |
.
├── scan_pdfs.py # Phase 0: Pre-scan detector
├── batch_ocr.py # Phase 1: Batch OCR scheduler
├── validate_ocr.py # Phase 2: Post-validation sampler
├── pdfexpert_ocr.scpt # AppleScript UI driver for PDF Expert
├── config.json # Configuration
├── requirements.txt # Python dependencies
├── ocr_queue.example.json # Example queue file
├── debug_*.scpt # Debug scripts for UI element discovery
├── logs/ # Runtime logs
├── output/ # OCR output directory
└── reports/ # Generated reports
This tool uses AppleScript UI Scripting (System Events) to automate PDF Expert's GUI:
- Open PDF in background (
open -g) to avoid window maximization - Activate PDF Expert and bring to frontmost (
activate+set frontmost to true) - Click menu: Scan → Recognize Text (扫描 → 识别文本)
- Wait for right panel to appear, then click the "识别..." button
- Handle confirmation dialog ("All pages" → "Apply")
- Poll for OCR completion (check progress indicator disappearance)
- Exit scan mode, save (⌘S), close window (⌘W)
- Quit PDF Expert (single-file mode) or keep open (batch mode)
Why foreground is required: PDF Expert's right-side OCR panel only renders when the app is truly frontmost. Background accessibility clicks can trigger menus but the panel elements are not exposed in the accessibility tree.
A: PDF Expert may need more time to load. Increase the delay after open -g in pdfexpert_ocr.scpt (line 17, default 4s).
A: The right panel did not load. Usually caused by:
- PDF Expert not being frontmost (another app stole focus)
- System popup blocking the UI (grant accessibility permissions)
- PDF Expert UI language mismatch (script expects Chinese UI)
A: Some PDF encodings (PNG + DeviceGray) are not supported by PDF Expert's OCR engine. No workaround — use alternative OCR tools for these files.
A: Each file requires foreground activation. Do not use the mouse/keyboard during batch processing. For large PDFs (>100 pages), use the chunking approach described above.
A: Change ocr_language in config.json. The script currently supports the language options available in PDF Expert's UI. For English PDFs, use "English".
- macOS only: Requires AppleScript and System Events accessibility
- PDF Expert dependency: UI element names are hardcoded in Chinese. If PDF Expert updates its UI, the script may need adjustment.
- Foreground requirement: Cannot run in true headless mode — PDF Expert must be frontmost during OCR
- Serial processing: Only one file at a time due to Accessibility API constraints
- PNG Gray-scale: Some PDF image encodings are not OCR-able by PDF Expert
- Chinese UI only: Currently tested with PDF Expert's Chinese interface. Other languages may require element name adjustments in
pdfexpert_ocr.scpt
If PDF Expert updates its UI and element names change, use the debug scripts to discover new element names:
# List all UI elements containing "识别"
osascript debug_search.scpt /path/to/test.pdf
# Deep recursive search of the window element tree
osascript debug_panel.scpt /path/to/test.pdf
# Full dump of all accessible elements
osascript full_dump.scpt /path/to/test.pdf
# Find language radio buttons
osascript debug_lang.scpt /path/to/test.pdfMIT License — feel free to use, modify, and distribute.
- PDF Expert by Readdle — excellent PDF OCR engine
- PyMuPDF — fast PDF text extraction and manipulation