Which Tools Does book-to-skill Use for PDF Extraction? A Complete Technical Breakdown
book-to-skill uses a tiered PDF extraction pipeline that combines native system tools (pdftotext, pdfinfo), pure-Python libraries (pypdf, pdfminer.six), advanced layout-preserving extraction (docling), and an optional ML-powered inspector (pdf-inspector/Firecrawl) to handle everything from plain text to complex technical PDFs.
The virgiliojr94/book-to-skill repository implements a robust, multi-layered approach to PDF extraction that gracefully degrades when optional dependencies are unavailable. This design ensures reliable text extraction across diverse PDF types—from simple ebooks to dense technical documents with tables, code blocks, and mathematical formulas.
The Four-Tier PDF Extraction Architecture
book-to-skill organizes its PDF extraction into distinct layers, each triggered based on availability and document complexity. The core implementation lives in book_to_skill/parsers/pdf.py, with dependency management centralized in book_to_skill/dependencies.py.
Tier 1: Fast Native Text Extraction with pdftotext
The preferred path for text-heavy PDFs uses pdftotext from poppler-utils, invoked via subprocess:
# From book_to_skill/parsers/pdf.py, lines 76-84
result = subprocess.run(
["pdftotext", "-layout", str(pdf_path), "-"],
capture_output=True,
text=True,
timeout=30
)
This approach preserves layout information and runs significantly faster than pure-Python alternatives. When pdftotext is missing, the system automatically falls back to Tier 2.
Tier 2: Pure-Python Fallbacks (pypdf and pdfminer.six)
Two libraries provide dependency-free extraction when native tools are unavailable.
pypdf — lightweight page-by-page extraction:
# From book_to_skill/parsers/pdf.py, lines 12-21
reader = pypdf.PdfReader(pdf_path)
text_parts = []
for page in reader.pages:
text_parts.append(page.extract_text() or "")
text = "\n".join(text_parts)
pdfminer.six — more sophisticated layout analysis:
# From book_to_skill/parsers/pdf.py, lines 33-41
from pdfminer.high_level import extract_text
text = extract_text(
str(pdf_path),
page_numbers=None, # all pages
maxpages=0
)
The pdfminer.six extractor inserts form-feed characters (\f) between pages, enabling reliable page-by-page processing downstream.
Tier 3: Technical PDF Processing with docling
For PDFs containing tables, code snippets, formulas, or complex multi-column layouts, docling provides structure-preserving Markdown conversion:
# From book_to_skill/parsers/pdf.py, lines 45-63
from docling.datamodel.base_models import InputFormat
from docling.datamodel.document_conversion import DocumentConverter, PdfPipelineOptions
pipeline_options = PdfPipelineOptions()
pipeline_options.do_table_structure = True # enable table detection
converter = DocumentConverter(
format_options={
InputFormat.PDF: PdfFormatOption(pipeline_options=pipeline_options)
}
)
result = converter.convert(pdf_path)
markdown = result.document.export_to_markdown()
This Tier 3 extraction is opt-in via the extraction_mode="technical" parameter, as it requires heavier dependencies and processing time.
Tier 4: Optional Smart Inspection with pdf-inspector
The book_to_skill/pdf_inspector_integration.py module provides an inspector-first path that can bypass the entire fallback chain:
# From pdf_inspector_integration.py, lines 45-53
from book_to_skill.pdf_inspector_integration import inspect_pdf
markdown, metadata = inspect_pdf("document.pdf")
if markdown and metadata.get("confidence", 0) > 0.8:
# Use inspector-provided Markdown directly
return markdown, metadata
else:
# Fall back to standard extraction pipeline
This pdf-inspector (Firecrawl-based) analyzes the PDF's internal structure and reports whether native text extraction will produce high-quality results. When confidence is high, it returns pre-extracted Markdown; otherwise, the standard pipeline takes over.
Auxiliary Tool: pdfinfo for Page Counting
When primary extraction methods fail to report page counts, book-to-skill falls back to the pdfinfo system command:
# From book_to_skill/parsers/pdf.py, lines 71-78
result = subprocess.run(
["pdfinfo", str(pdf_path)],
capture_output=True,
text=True
)
# Parse output for "Pages: N" line
This ensures accurate progress reporting and metadata even when document parsing encounters errors.
Dependency Management and Graceful Degradation
The book_to_skill/dependencies.py module (lines 25-31) declares these tools as optional dependency groups:
| Dependency Group | Tools | Install Command |
|---|---|---|
pdf-text |
pypdf, pdfminer.six |
pip install book-to-skill[pdf-text] |
pdf-native |
pdftotext, pdfinfo (system) |
apt-get install poppler-utils |
pdf-technical |
docling |
pip install book-to-skill[pdf-technical] |
pdf-inspector |
pdf-inspector (Firecrawl) |
pip install book-to-skill[pdf-inspector] |
When tools are missing, book-to-skill emits targeted installation hints:
$ book-to-skill extract document.pdf
[WARNING] pdftotext not found. Install with: sudo apt-get install poppler-utils
[INFO] Falling back to pypdf extractor...
Practical Usage Examples
Basic CLI Extraction
# Default: tries pdftotext → pypdf → pdfminer.six
book-to-skill extract path/to/document.pdf
# Force technical mode for table/code extraction
book-to-skill extract --mode technical complex_tutorial.pdf
Programmatic Single-File Extraction
from pathlib import Path
from book_to_skill import utils
result = utils.extract_single_file(
Path("my_book.pdf"),
extraction_mode="text", # or "technical"
install_mode="ask" # "auto", "ask", or "skip"
)
print(f"Extracted {result['pages']} pages")
print(result["text"][:2000]) # First 2000 characters
Conditional Inspector Usage
from book_to_skill.pdf_inspector_integration import inspect_pdf
from book_to_skill.parsers.pdf import extract_text_with_fallback
def smart_extract(pdf_path):
# Attempt inspector shortcut
markdown, meta = inspect_pdf(pdf_path)
if markdown and meta.get("confidence", 0) > 0.85:
return markdown, "inspector"
# Full fallback pipeline
return extract_text_with_fallback(pdf_path), "fallback"
Key Implementation Files
| File | Lines of Interest | Purpose |
|---|---|---|
book_to_skill/parsers/pdf.py |
12-21, 33-41, 45-63, 71-84 | Core extractors for all four tiers |
book_to_skill/dependencies.py |
25-31 | Optional dependency declarations |
book_to_skill/pdf_inspector_integration.py |
45-53 | Inspector hook and confidence logic |
scripts/extract.py |
— | CLI entry point wiring components |
Summary
pdftotext(poppler-utils) provides the fastest, layout-preserving native extraction when availablepypdfandpdfminer.sixserve as pure-Python fallbacks requiring no system dependenciesdoclinghandles complex technical PDFs with tables, code, and formulas via Markdown exportpdf-inspector(Firecrawl) offers optional ML-powered pre-inspection that can bypass slower methodspdfinfosupplies reliable page counts as an auxiliary system command- The dependency manager in
dependencies.pyensures graceful degradation with actionable install hints
Frequently Asked Questions
Is pdftotext required to use book-to-skill?
No. While pdftotext provides the best performance for text-heavy PDFs, book-to-skill automatically falls back to pypdf and pdfminer.six when poppler-utils is unavailable. The pure-Python fallback chain requires no system package installation.
When should I use extraction_mode="technical" instead of "text"?
Use "technical" for PDFs containing structured data—tables, code blocks, mathematical notation, or multi-column academic papers. This mode activates docling, which preserves document structure as Markdown. For novels, articles, or other primarily textual content, "text" mode is faster and produces cleaner output.
Does the pdf-inspector integration work offline?
No. The pdf-inspector (implemented via Firecrawl in pdf_inspector_integration.py) requires network access to analyze PDF structure. It is purely optional; the standard four-tier extraction pipeline functions completely offline.
How does book-to-skill handle corrupted or image-based PDFs?
For image-based PDFs without embedded text, all text extraction tiers (pdftotext, pypdf, pdfminer.six) will return empty or minimal text. The docling technical extractor may still capture visual structure, but true OCR is not currently implemented in the core pipeline. The pdf-inspector will typically report low confidence for such documents, triggering appropriate fallback behavior.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →