doocus first ver
This commit is contained in:
73
doocus/extractors/pdf.py
Normal file
73
doocus/extractors/pdf.py
Normal file
@@ -0,0 +1,73 @@
|
||||
"""
|
||||
PDF-family extractor.
|
||||
|
||||
Text per page via pypdf, plus the document info dict (title/author/dates). When
|
||||
options['render'] is set and pdf2image (+ system poppler) is available, page 1 is
|
||||
rendered to thumb.jpg.
|
||||
"""
|
||||
import io
|
||||
from pathlib import Path
|
||||
|
||||
from .base import ExtractionResult
|
||||
|
||||
EXTRACTOR_ID = "pdf/pypdf@1"
|
||||
|
||||
|
||||
def _info_metadata(reader) -> dict:
|
||||
out = {}
|
||||
info = getattr(reader, "metadata", None)
|
||||
if not info:
|
||||
return out
|
||||
for src, dst in (("title", "title"), ("author", "author"),
|
||||
("creation_date", "created"), ("modification_date", "modified_doc")):
|
||||
try:
|
||||
val = getattr(info, src, None)
|
||||
except Exception:
|
||||
val = None
|
||||
if val:
|
||||
out[dst] = str(val)
|
||||
return out
|
||||
|
||||
|
||||
def _render_first_page(source: Path) -> bytes:
|
||||
from pdf2image import convert_from_path # needs system poppler
|
||||
images = convert_from_path(str(source), first_page=1, last_page=1, dpi=100)
|
||||
if not images:
|
||||
return b""
|
||||
im = images[0]
|
||||
im.thumbnail((640, 640))
|
||||
buf = io.BytesIO()
|
||||
im.convert("RGB").save(buf, format="JPEG", quality=80)
|
||||
return buf.getvalue()
|
||||
|
||||
|
||||
def extract(source: Path, options: dict) -> ExtractionResult:
|
||||
from pypdf import PdfReader # lazy
|
||||
|
||||
warnings = []
|
||||
reader = PdfReader(str(source))
|
||||
pages = reader.pages
|
||||
blocks = []
|
||||
for i, page in enumerate(pages, 1):
|
||||
try:
|
||||
text = page.extract_text() or ""
|
||||
except Exception as e:
|
||||
text = ""
|
||||
warnings.append(f"page {i} text extraction failed: {e}")
|
||||
blocks.append(f"## Page {i}\n\n{text.strip()}")
|
||||
content = "\n\n".join(blocks) + "\n"
|
||||
|
||||
metadata = _info_metadata(reader)
|
||||
metadata["pages"] = len(pages)
|
||||
|
||||
thumb = None
|
||||
if options.get("render"):
|
||||
try:
|
||||
thumb = _render_first_page(source) or None
|
||||
except ImportError:
|
||||
warnings.append("--render requested but pdf2image/poppler not available")
|
||||
except Exception as e:
|
||||
warnings.append(f"page render failed: {e}")
|
||||
|
||||
return ExtractionResult(content=content, metadata=metadata, thumb=thumb,
|
||||
warnings=warnings, extractor=EXTRACTOR_ID)
|
||||
Reference in New Issue
Block a user