#pdf #text #converters #pdftotext
#PDF #текст #конвертеры #pdftotext
Вопрос:
Я пытаюсь конвертировать pdf в текстовые файлы. Проблема в том, что эти PDF содержат изображения, которые меня не волнуют (это тип файла, который я хочу извлечь (https://www.sia.aviation-civile.gouv.fr/pub/media/store/documents/file/l/f/lf_sup_2020_213_fr.pdf ). Обратите внимание, что если я копирую / вставляю с помощью мыши, это работает довольно хорошо (за исключением разрыва строки), поэтому я предполагаю, что это возможно. Большинство ответов, которые я нашел в Интернете, довольно хорошо работают с фиктивным PDF только с текстом, но дают особенно плохой результат на карте. Например, что-то вроде этого
from tika import parser # pip install tika
raw = parser.from_file('test2.pdf')
print(raw['content'])
хорошо работает для извлечения текста, но у меня много такого мусора :
ОЧЕНЬ
CTR
3
CH
A
которые появляются из-за карты.
Что-то вроде этого, которое работает путем преобразования pdf в изображения, а затем чтения изображений, сталкивается с той же проблемой (я нашел это в очень похожей теме в stackoverflow, но ответа нет) :
import pytesseract as pt
from PIL import Image
import sys
def convert(name):
pages = convert_from_path(name, dpi=200)
for idx,page in enumerate(pages):
page.save('page' str(idx) '.jpg', 'JPEG')
quote = Image.open('page' str(idx) '.jpg')
text = pt.image_to_string(quote, lang="fra")
file_ex = open('page' str(idx) '.text',"w")
file_ex.write(text)
file_ex.close()
if __name__ == '__main__':
convert(sys.argv[1])
Наконец, я попытался сначала удалить изображение, а затем использовать одно из приведенных выше решений, но это не сработало лучше :
from tika import parser # pip install tika
from PyPDF2 import PdfFileWriter, PdfFileReader
# Remove the images
inputStream = open("lf_sup_2020_213_fr.pdf", "rb")
outputStream = open("test3.pdf", "wb")
src = PdfFileReader(inputStream)
output = PdfFileWriter()
[output.addPage(src.getPage(i)) for i in range(src.getNumPages())]
output.removeImages()
output.write(outputStream)
outputStream.close()
# Read from pdf without images
raw = parser.from_file('test2.pdf')
print(raw['content'])
Вы знаете, как это решить? Это может быть на любом языке.
Спасибо
Ответ №1:
Один из подходов, который вы могли бы попробовать, — это использовать инструментарий, способный анализировать текстовые символы в PDF, а затем использовать свойства объекта, чтобы попытаться удалить ненужные метки карты, сохраняя при этом требуемые текстовые символы.
Например, метод ParsePages из LEADTOOLS PDF toolkit (с которым я знаком, поскольку работаю у поставщика этого инструментария) можно использовать для получения текста из PDF:
using (PDFDocument document = new PDFDocument(pdfFileName))
{
PDFParsePagesOptions options = PDFParsePagesOptions.All;
document.ParsePages(options, 1, -1);
using (StreamWriter writer = File.CreateText(txtFileName))
{
IList<PDFObject> objects = document.Pages[0].Objects;
writer.WriteLine("Objects: {0}", objects.Count);
foreach (PDFObject obj in objects)
{
if (obj.TextProperties.IsEndOfLine)
writer.WriteLine(obj.Code);
else
writer.Write(obj.Code);
}
writer.WriteLine("---------------------");
}
}
Это приведет к получению всего текста в формате PDF для первой страницы с нежелательными результатами, как вы упомянули. Вот выдержка ниже:
Objects: 3918
5
91L
F5
4
1 LF
N
OY
L2
1AM
TService
8
26
1de l’Information
0
B09SUP AIP 213/20
7
Aéronautique
Date de publication : 05 NOV
e-mail : sia.qualite@aviation-civile.gouv.fr
Internet : www.sia.aviation-civile.gouv.fr
141
17˚
82
N20
9Objet : Création de 4 zones réglementées temporaires (ZRT) pour l’exercice VOLOPS en région de Chambéry
En vigueur : Du mercredi 25 Novembre 2020 au vendredi 04 décembre 2020
Для проверки свойств каждого анализируемого символа можно использовать дополнительный код:
writer.WriteLine(" ObjectType: {0}", obj.ObjectType.ToString());
writer.WriteLine(" Bounds: {0}, {1}, {2}, {3}", obj.Bounds.Left, obj.Bounds.Top, obj.Bounds.Right, obj.Bounds.Bottom);
writer.WriteLine(" TextProperties.FontHeight: {0}", obj.TextProperties.FontHeight.ToString());
writer.WriteLine(" TextProperties.FontIndex: {0}", obj.TextProperties.FontIndex.ToString());
writer.WriteLine(" Code: {0}", obj.Code);
writer.WriteLine("------");
Это даст свойства для каждого символа:
Objects: 3918
ObjectType: Text
Bounds: -60.952693939209, 1017.25231933594, -51.8431816101074, 1023.71826171875
TextProperties.FontHeight: 7.10454273223877
TextProperties.FontIndex: 48
Code: 5
------
Используя эти свойства, нежелательный текст может быть отфильтрован с использованием их свойств. Например, я заметил, что высота шрифта для значительной части нежелательного текста составляет около 7 единиц формата PDF, поэтому первый код может быть изменен, чтобы избежать извлечения любого текста размером менее 7,25 единиц формата PDF:
foreach (PDFObject obj in objects)
{
if (obj.TextProperties.FontHeight > 7.25)
{
if (obj.TextProperties.IsEndOfLine)
writer.WriteLine(obj.Code);
else
writer.Write(obj.Code);
}
}
Извлеченный результат даст лучший результат, ниже приводится выдержка:
Objects: 3918
Service
de l’Information
SUP AIP 213/20
Aéronautique
Date de publication : 05 NOV
e-mail : sia.qualite@aviation-civile.gouv.fr
Internet : www.sia.aviation-civile.gouv.fr
Objet : Création de 4 zones réglementées temporaires (ZRT) pour l’exercice VOLOPS en région de Chambéry
En vigueur : Du mercredi 25 Novembre 2020 au vendredi 04 décembre 2020
Lieu : FIR : Marseille LFMM - AD : Chambéry Aix-Les-Bains LFLB, Chambéry Challes les Eaux LFLE
ZRT LE SIRE, MOTTE CASTRALE, ALLEVARD
*
C
D
E
В конце концов, вам нужно будет попытаться найти хорошие критерии для фильтрации нежелательного текста, не удаляя текст, который вам нужно сохранить, используя этот подход.