Source code for dedoc.metadata_extractors.concrete_metadata_extractors.pdf_metadata_extractor

import logging
import os
from typing import Optional

from PyPDF2 import PdfFileReader
from PyPDF2.utils import PdfReadError

from dedoc.metadata_extractors.concrete_metadata_extractors.base_metadata_extractor import BaseMetadataExtractor
from dedoc.utils.utils import convert_datetime


[docs]class PdfMetadataExtractor(BaseMetadataExtractor): """ This class is used to extract metadata from pdf documents. It expands metadata retrieved by :class:`~dedoc.metadata_extractors.BaseMetadataExtractor`. In addition to them, the following fields can be added to the metadata other fields: - producer; - creator; - author; - title; - subject; - keywords; - creation date; - modification date. """
[docs] def __init__(self, *, config: dict) -> None: """ :param config: configuration of the extractor, e.g. logger for logging """ super().__init__() self.keys = { "/Producer": "producer", "/Creator": "creator", "/Author": "author", "/Title": "title", "/Subject": "subject", "/Keywords": "keywords" } self.keys_date = { "/CreationDate": "creation_date", "/ModDate": "modification_date", } self.config = config self.logger = config.get("logger", logging.getLogger())
[docs] def can_extract(self, directory: str, filename: str, converted_filename: str, original_filename: str, parameters: dict = None, other_fields: Optional[dict] = None) -> bool: """ Check if the document has .pdf extension. Look to the :meth:`~dedoc.metadata_extractors.AbstractMetadataExtractor.can_extract` documentation to get the information about parameters. """ return filename.lower().endswith(".pdf")
[docs] def extract_metadata(self, directory: str, filename: str, converted_filename: str, original_filename: str, parameters: dict = None, other_fields: Optional[dict] = None) -> dict: """ Add the predefined list of metadata for the pdf documents. Look to the :meth:`~dedoc.metadata_extractors.AbstractMetadataExtractor.extract_metadata` documentation to get the information about parameters. """ result = super().extract_metadata(directory=directory, filename=filename, converted_filename=converted_filename, original_filename=original_filename, parameters=parameters, other_fields=other_fields) path = os.path.join(directory, filename) pdf_fields = self._get_pdf_info(path) if len(pdf_fields) > 0: result["other_fields"] = {**result.get("other_fields", {}), **pdf_fields} return result
def _get_pdf_info(self, path: str) -> dict: try: with open(path, "rb") as file: document = PdfFileReader(file) document_info = document.getDocumentInfo() if document.getDocumentInfo() is not None else {} result = self.__prettify_metadata(document_info) return result except PdfReadError: return {"broken_pdf": True} except Exception as e: self.logger.warning(f"exception while extract pdf metadata: {path} {e}") if self.config.get("debug_mode", False): raise e return {"broken_pdf": True} def __prettify_metadata(self, document_info: dict) -> dict: result = {} for key, value in document_info.items(): if isinstance(value, str) and len(value) > 0: if key in self.keys: result[self.keys[key]] = value elif key in self.keys_date: try: date = convert_datetime(value) except: # noqa date = None if date is not None: result[self.keys_date[key]] = date return result