PDF에서 문자 정보를 추출하려면 PDFMiner 선택
17521 단어 Python3파이썬dockerfilepdfminer도커
PDF에서 문자 정보를 추출하기 위해
환경 구축
DockerfileFROM 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.txtpandas==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
PDF에서 문자 정보 추출
컨테이너 생성에 성공하면 자동으로 Jupiter가 시작되므로 파이썬 파일을 만듭니다.
아래 설정은 최소한의 문자 정보를 추출하여 텍스트 파일에 저장하는 코드입니다.
이번에는 금융청의 PDF를 test.pdf로 했습니다.
htps //w w. f. . jp / 네 ws / 30 / wp / 슈퍼 r ゔ ぃ ry_ 앗 p pdf
test.pyfrom 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) # ページを処理する。
layout = device.get_result() # LTPageオブジェクトを取得。
boxes = find_textboxes(layout)
for box in boxes:
write_text(text_file, box.get_text().strip())
text_file.close()
laparams에 의한 조정
텍스트가 생각대로 검색할 수 없는 경우 laparams 매개 변수를 조정합니다. char_margin, word_margin, line_margin을 변경하면 그룹화되는 문자가 변경됩니다.
detect_vertivcal은 일본어처럼 세로 쓰기 문장이 있으면 True로 설정합니다.
test.pyinterpreter, device = pdfminer_config(line_overlap=0.5, word_margin=0.1, char_margin=2.0, line_margin=0.5, detect_vertical=False)
boxes 내용
위의 코드에서 얻은 boxes에는 다양한 정보가 담겨 있습니다.
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
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
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) # ページを処理する。
layout = device.get_result() # LTPageオブジェクトを取得。
boxes = find_textboxes(layout)
for box in boxes:
write_text(text_file, box.get_text().strip())
text_file.close()
interpreter, device = pdfminer_config(line_overlap=0.5, word_margin=0.1, char_margin=2.0, line_margin=0.5, detect_vertical=False)
print(boxes[0])
# >> <LTTextBoxHorizontal(0) 92.160,755.000,524.296,766.952 'かし、従来は金融庁の国際部門は国際規制の導入負担ができるだけ小さくなるよう交\n'>
print(boxes[0].get_text())
# >> かし、従来は金融庁の国際部門は国際規制の導入負担ができるだけ小さくなるよう交
print(boxes[0].bbox)
# >> (92.15997480600001, 754.9998879965001, 524.2961793060001, 766.9523361965001)
# >> タプルの中は(x0, y0, x1, y1)の順になっており、示す位置は画像のようになっています。
lines의 내용
일부 박스에서는 LTTextLine이 목록으로 나열됩니다. 따라서 이전 코드에서 사용하지 않은 find_textline을 사용하여 LTTextLine을 얻으십시오.
test.py
lines = find_textlines(boxes[0])
print(lines[0])
# >><LTTextLineHorizontal 92.160,755.000,524.296,766.952 'かし、従来は金融庁の国際部門は国際規制の導入負担ができるだけ小さくなるよう交\n'>
print(lines[0].get_text())
# >> かし、従来は金融庁の国際部門は国際規制の導入負担ができるだけ小さくなるよう交
print(lines[0].bbox)
# >> (92.15997480600001, 754.9998879965001, 524.2961793060001, 766.9523361965001)
characters 내용
또한 일부 라인에서는 LTChar가 목록으로 나란히 있습니다. 그 중에는 문자 정보와 위치 정보 외에도 font 등도 막혀 있습니다.
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='か'>
print(characters[0].get_text())
# >> か
print(characters[0].bbox)
# >> (92.15997480600001, 754.9998879965001, 104.16042480600001, 766.9523361965001)
시간이 생기면, 취득할 수 있던 부분의 색을 바꾸는 등도 소개하고 싶습니다.
Reference
이 문제에 관하여(PDF에서 문자 정보를 추출하려면 PDFMiner 선택), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/fumitrial8/items/f3d92fca0de409feaee9텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)