How to Analyze a PDF with the layout-parser package. | by Brendan Ferris | Towards Data Science

I recently was involved with a project that required parsing of a PDF in order to identify the regions of page and return the text from those regions. The text regions would then be fed to a Q/A model (farm-haystack), and return extracted data from the PDF. Essentially, we wanted the computer to read PDF’s for us and tell us what it found. Currently, there are a few popular modules that perform this task with varying effectiveness, namely, pdfminer and py2pdf. The problem is that table data is very hard to parse/detect. The solution? Take out the tables a figures, return only the text blocks.
pip install layoutparser
We need to convert each page of the PDF to an image in order to perform OCR on it and extract the text blocks. There are many different ways to do this. You could convert the PDF and save the image on your local machine. But for our purposes we want to save the image of the PDF page in memory temporarily -> extract text -> discard image, because after we perform OCR we no longer need the image (we would still have the original pdf file). To solve this problem, we will use the pdf2image package:
pip install pdf2image 
This package will allow us to input a PDF file, and output each page a an image. We can choose to save the image on a storage medium, or process the PDF as a list of PIL images temporarily then discard them when we are done.
images = convert_from_bytes(open('FILE PATH', 'rb').read())
Now, you will have a list of images that you can loop through.
In order for these images to be readable by the layout-parser package, you need to convert them to an array of pixel values, which can be achieved easily with numpy.
image = np.array(image)
Currently, there are two OCR tools that you can use with this package: Google Cloud Vision (GCV) and Tesseract. We will use Tesseract. To Detect the regions of the page, there are pre-trained deep learning models that are available for various use cases (tables, magazine publications, scholarly journals) we will use a model called PubLayNet which is specific to scholarly journals. Keep in mind that there are ways to train custom models for your specific use case.
model = lp.Detectron2LayoutModel(            config_path ='lp://PubLayNet/mask_rcnn_X_101_32x8d_FPN_3x/config', # In model catalog            label_map   = {0: "Text", 1: "Title", 2: "List", 3:"Table", 4:"Figure"}, # In model`label_map`            extra_config=["MODEL.ROI_HEADS.SCORE_THRESH_TEST", 0.8] # Optional        )#loop through each pagefor image in images:    ocr_agent = lp.ocr.TesseractAgent()        image = np.array(image)        layout = model.detect(image)text_blocks = lp.Layout([b for b in layout if b.type == 'Text']) #loop through each text box on page.        for block in text_blocks:        segment_image = (block                        .pad(left=5, right=5, top=5, bottom=5)                        .crop_image(image))        text = ocr_agent.detect(segment_image)        block.set(text=text, inplace=True)            for i, txt in enumerate(text_blocks.get_texts()):            my_file = open("OUTPUT FILE PATH/FILENAME.TXT","a+")            my_file.write(txt)
After running the above code, you can pick out the regions of each page that you are interested in using the following syntax:
text_blocks = lp.Layout([b for b in layout if b.type == 'Text'])title_blocks = lp.Layout([b for b in layout if b.type == 'Title'])list_blocks = lp.Layout([b for b in layout if b.type == 'List'])table_blocks = lp.Layout([b for b in layout if b.type == 'Table'])figure_blocks = lp.Layout([b for b in layout if b.type == 'Figure'])
Now, you can will be able to extract text from the portions of the page you are interested in, and disregard the portions that you don’t need.
Thus far, the layout-parser package has proved to be the most reliable and easiest tool for analyzing the structure of a page. In this short tutorial we focused on being able to intake a whole (multi-page) PDF and extracting machine readable portions of the page that can then be fed into an NLP model for analysis. For more information, refer to the documentation!