Modularize PDF w/ Page and Container classes

Container
|-- Page
|-- PDF
    |-- .pages
This commit is contained in:
Jeremy Singer-Vine
2016-03-02 15:26:23 -05:00
parent 4d33a2e54d
commit 5af89c8f70
+75 -61
View File
@@ -11,67 +11,7 @@ from pdfminer.converter import PDFPageAggregator
import re
lt_pat = re.compile(r"^LT")
class PDF(object):
def __init__(self, file_or_buffer, pages=None, laparams=None):
self.laparams = None if laparams == None else LAParams(**laparams)
rsrcmgr = PDFResourceManager()
self.doc = PDFDocument(PDFParser(file_or_buffer))
self.device = PDFPageAggregator(rsrcmgr, laparams=self.laparams)
self.interpreter = PDFPageInterpreter(rsrcmgr, self.device)
self.pages = []
page_iter = (p for i, p in enumerate(PDFPage.create_pages(self.doc))
if pages == None or i+1 in pages)
for page in page_iter:
self.interpreter.process_page(page)
layout = self.device.get_result()
self.pages.append(layout)
self.objects = self.parse()
def parse(self):
objects = {}
def process_object(obj, page):
_round = lambda x: round(x, 3) if type(x) == float else x
attr = dict((k, _round(v)) for k, v in obj.__dict__.items()
if isinstance(v, (float, int, string_types))
and k[0] != "_")
kind = re.sub(lt_pat, "", obj.__class__.__name__).lower()
attr["object_type"] = kind
attr["pageid"] = page.pageid
if hasattr(obj, "get_text"):
attr["text"] = obj.get_text()
if attr.get("y0") != None:
page_index = self.pages.index(page)
prev_h = sum(p.height for p in self.pages[:page_index])
attr["top"] = _round(page.height - attr["y1"])
attr["doctop"] = _round(prev_h + attr["top"])
if objects.get(kind) == None:
objects[kind] = []
objects[kind].append(attr)
if hasattr(obj, "_objs"):
for child in obj._objs:
process_object(child, page)
def process_page(page):
for child in page._objs:
process_object(child, page)
for page in self.pages:
process_page(page)
return objects
class Container(object):
@property
def rects(self):
return self.objects.get("rect", [])
@@ -95,3 +35,77 @@ class PDF(object):
@property
def annos(self):
return self.objects.get("anno", [])
class Page(Container):
def __init__(self, layout, initial_doctop=0):
self.layout = layout
self.width = layout.width
self.height = layout.height
self.pageid = layout.pageid
self.initial_doctop = 0
self.objects = self.parse_objects()
def parse_objects(self):
objects = {}
_round = lambda x: round(x, 3) if type(x) == float else x
def process_object(obj):
attr = dict((k, _round(v)) for k, v in obj.__dict__.items()
if isinstance(v, (float, int, string_types))
and k[0] != "_")
kind = re.sub(lt_pat, "", obj.__class__.__name__).lower()
attr["object_type"] = kind
attr["pageid"] = self.pageid
if hasattr(obj, "get_text"):
attr["text"] = obj.get_text()
if attr.get("y0") != None:
attr["top"] = _round(self.layout.height - attr["y1"])
attr["doctop"] = _round(self.initial_doctop + attr["top"])
if objects.get(kind) == None:
objects[kind] = []
objects[kind].append(attr)
if hasattr(obj, "_objs"):
for child in obj._objs:
process_object(child)
for obj in self.layout._objs:
process_object(obj)
return objects
class PDF(Container):
def __init__(self, file_or_buffer, pages=None, laparams=None):
self.laparams = None if laparams == None else LAParams(**laparams)
rsrcmgr = PDFResourceManager()
self.doc = PDFDocument(PDFParser(file_or_buffer))
self.device = PDFPageAggregator(rsrcmgr, laparams=self.laparams)
self.interpreter = PDFPageInterpreter(rsrcmgr, self.device)
self.pages = []
page_iter = (p for i, p in enumerate(PDFPage.create_pages(self.doc))
if pages == None or i+1 in pages)
doctop = 0
for page in page_iter:
self.interpreter.process_page(page)
layout = self.device.get_result()
p = Page(layout, initial_doctop=doctop)
self.pages.append(p)
doctop += p.layout.height
@property
def objects(self):
all_objects = {}
for p in self.pages:
for kind in p.objects.keys():
all_objects[kind] = all_objects.get(kind, []) + p.objects[kind]
return all_objects