diff --git a/pdfplumber/pdf.py b/pdfplumber/pdf.py index 56bf057..ee57797 100644 --- a/pdfplumber/pdf.py +++ b/pdfplumber/pdf.py @@ -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