[PYTHON] Sélectionnez PDFMiner pour extraire les informations textuelles du PDF

Pour extraire des informations textuelles d'un PDF

Environnement

Dockerfile


FROM python:3.6
ENV LC_ALL C.UTF-8
ENV LANG C.UTF-8  
RUN apt-get -y update && \
    apt-get install -y --fix-missing \
    build-essential \
    software-properties-common \
    poppler-utils && \
    apt-get clean && \
    rm -rf /tmp/* /var/tmp/* && \
    mkdir /api
WORKDIR /api
COPY requirements.txt /api/requirements.txt
RUN pip3 install --upgrade pip && \
    pip3 install --upgrade -r requirements.txt
EXPOSE 8888
ENTRYPOINT jupyter notebook --ip=0.0.0.0 --allow-root --no-browser

requirements.txt


pandas==0.24.2
pillow==7.0.0
opencv-python==3.4.2.16
pdfminer==20191125
jupyter==1.0.0
$ docker build -t pdfminer -f ./Dockerfile .
$ docker run -it -v `pwd`:/api -p 8888:8888 --name pdfminer pdfminer bash

Extraire les informations textuelles du PDF

Si le conteneur est créé avec succès, Jupiter démarrera automatiquement, créez donc un fichier python. Les paramètres suivants sont le code permettant d'extraire au moins les informations de caractère et de les enregistrer dans un fichier texte. Cette fois, le PDF de l'Agence des services financiers est test.pdf. https://www.fsa.go.jp/news/30/wp/supervisory_approaches_revised.pdf

test.py


from pdfminer.converter import PDFPageAggregator
from pdfminer.layout import LAParams, LTContainer, LTTextBox, LTTextLine, LTChar
from pdfminer.pdfinterp import PDFPageInterpreter, PDFResourceManager
from pdfminer.pdfpage import PDFPage

def pdfminer_config(line_overlap, word_margin, char_margin,line_margin, detect_vertical):
    laparams = LAParams(line_overlap=line_overlap,
                        word_margin=word_margin,
                        char_margin=char_margin,
                        line_margin=line_margin,
                        detect_vertical=detect_vertical)
    resource_manager = PDFResourceManager()
    device = PDFPageAggregator(resource_manager, laparams=laparams)
    interpreter = PDFPageInterpreter(resource_manager, device)
    return (interpreter, device)

def find_textboxes(layout_obj):
    if isinstance(layout_obj, LTTextBox):
        return [layout_obj]
    if isinstance(layout_obj, LTContainer):
        boxes = []
        for child in layout_obj:
            boxes.extend(find_textboxes(child))
        return boxes
    return []

def find_textlines(layout_obj):
    if isinstance(layout_obj, LTTextLine):
        return [layout_obj]
    if isinstance(layout_obj, LTTextBox):
        lines = []
        for child in layout_obj:
            lines.extend(find_textlines(child))
        return lines
    return []

def find_characters(layout_obj):
    if isinstance(layout_obj, LTChar):
        return [layout_obj]
    if isinstance(layout_obj, LTTextLine):
        characters = []
        for child in layout_obj:
            characters.extend(find_characters(child))
        return characters
    return []

def write_text(text_file, text):
    text_file.write(text)

text_file = open('output.txt', 'w')
with open("./test.pdf", 'rb') as f:
    interpreter, device = pdfminer_config(line_overlap=0.5, word_margin=0.1, char_margin=2, line_margin=0.5, detect_vertical=True)
    for page in PDFPage.get_pages(f):
        interpreter.process_page(page)  #Traitez la page.
        layout = device.get_result()  #Obtenez l'objet LTPage.
        boxes = find_textboxes(layout)
        for box in boxes:
            write_text(text_file, box.get_text().strip())
        
text_file.close()

Réglage par laparams

Si vous n'obtenez pas le texte souhaité, ajustez les paramètres dans laparams. En changeant char_margin, word_margin, line_margin, les caractères groupés changeront. définissez detect_vertivcal sur True s'il existe des phrases verticales telles que le japonais.

test.py


interpreter, device = pdfminer_config(line_overlap=0.5, word_margin=0.1, char_margin=2.0, line_margin=0.5, detect_vertical=False)

スクリーンショット 2020-01-18 11.53.36.png

Contenu des boîtes

Les boîtes disponibles dans le code ci-dessus contiennent de nombreuses informations.

print(boxes[0])
# >> <LTTextBoxHorizontal(0) 92.160,755.000,524.296,766.952 'Cependant, dans le passé, le département international de l'Agence des services financiers a échangé des informations afin que le fardeau de l'introduction de réglementations internationales soit aussi réduit que possible.\n'>
print(boxes[0].get_text())
# >>Cependant, dans le passé, le département international de l'Agence des services financiers a échangé des informations afin que le fardeau de l'introduction de réglementations internationales soit aussi réduit que possible.
print(boxes[0].bbox)
# >> (92.15997480600001, 754.9998879965001, 524.2961793060001, 766.9523361965001)
# >>À l'intérieur du taple(x0, y0, x1, y1)Les positions indiquées sont celles illustrées sur l'image.

スクリーンショット 2020-01-18 11.46.08.png

Contenu des lignes

Les LTTextLines sont répertoriées dans la boîte. Prenons donc la LTTextLine en utilisant find_textline, que nous n'avons pas utilisé dans le code ci-dessus.

test.py


lines = find_textlines(boxes[0])
print(lines[0])
# >><LTTextLineHorizontal 92.160,755.000,524.296,766.952 'Cependant, dans le passé, le département international de l'Agence des services financiers a échangé des informations afin que le fardeau de l'introduction de réglementations internationales soit aussi réduit que possible.\n'>
print(lines[0].get_text())
# >>Cependant, dans le passé, le département international de l'Agence des services financiers a échangé des informations afin que le fardeau de l'introduction de réglementations internationales soit aussi réduit que possible.
print(lines[0].bbox)
# >> (92.15997480600001, 754.9998879965001, 524.2961793060001, 766.9523361965001)

Contenu des caractères

De plus, LTChar est répertorié dans les lignes. En plus des informations sur les caractères et les informations de position, les polices y sont également intégrées.

test.py


characters = find_characters(lines[0])
print(characters[0])
# >><LTChar 92.160,755.000,104.160,766.952 matrix=[12.00,0.00,0.00,12.00, (92.16,756.68)] font='AHTYXM+MS-PGothic' adv=1.0 text='Ou'>
print(characters[0].get_text())
# >>Ou
print(characters[0].bbox)
# >> (92.15997480600001, 754.9998879965001, 104.16042480600001, 766.9523361965001)

Si j'ai le temps, je voudrais vous présenter comment changer la couleur de la pièce acquise.

Recommended Posts

Sélectionnez PDFMiner pour extraire les informations textuelles du PDF
Extraire du texte japonais d'un PDF avec PDFMiner
Conversion de pdf en txt 1 [pdfminer]
Conversion de pdf en txt 2 [pyocr]
Extraire du texte d'images avec Python
Convertissez un grand nombre de fichiers PDF en fichiers texte à l'aide de pdfminer
Extraire le texte du pdf [python] et lire les caractères à haute voix avec Open-Jtalk
Convertir un PDF joint en courrier électronique au format texte
Est-il possible d'extraire les informations de profil de la personne du journal de discussion?
Comment extraire le coefficient de la formule minute
[Python] Suite - Convertir le texte PDF en CSV page par page
J'ai essayé d'extraire diverses informations du PC distant de Python par la bibliothèque WMI
Extraire des images et des tableaux de pdf avec python pour réduire la charge de reporting
Somme de 1 à 10
Les images créées avec matplotlib passent de dvi à pdf
[Python] Convertir le texte PDF en CSV pour chaque page (2/24 postscript)
[Python] Changer l'entrée standard du clavier en fichier texte
Passer des informations confidentielles de SSM à ECS avec CloudFormation
Vous permet de sélectionner par nom à partir du nom d'utilisateur Django