如何将带有我不关心的图像的 PDF 转换为文本?
How to convert PDF with images which I don't care about to text?
我正在尝试将 pdf 转换为文本文件。问题是那些 pdf 包含我不关心的图像(这是我要提取的文件类型 (https://www.sia.aviation-civile.gouv.fr/pub/media/store/documents/file/l/f/lf_sup_2020_213_fr.pdf)。请注意,如果我用鼠标 copy/paste,它工作得很好(除了换行符),所以我猜这是可能的。我在网上找到的大部分答案在只有文本的虚拟 pdf 上工作得很好,但在地图上给出的结果特别糟糕。
例如,像这样
from tika import parser # pip install tika
raw = parser.from_file('test2.pdf')
print(raw['content'])
检索文本效果很好,但我有很多像这样的垃圾:
ERY
CTR
3
CH
A
因地图而出现
像这样的东西,它通过将 pdf 转换为图像然后读取图像来工作,面临同样的问题(我在 Whosebug 上的一个非常相似的线程上找到它,但没有答案):
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'])
你知道怎么解决吗?它可以是任何语言。
谢谢
您可以尝试的一种方法是使用能够解析 PDF 中文本字符的工具包,然后使用对象属性尝试删除不需要的地图标签,同时保留所需的文本字符。
例如,ParsePages method from 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
最后,您将不得不尝试提出一个好的标准来过滤掉不需要的文本,而不删除您需要保留的文本,使用这种方法。
我正在尝试将 pdf 转换为文本文件。问题是那些 pdf 包含我不关心的图像(这是我要提取的文件类型 (https://www.sia.aviation-civile.gouv.fr/pub/media/store/documents/file/l/f/lf_sup_2020_213_fr.pdf)。请注意,如果我用鼠标 copy/paste,它工作得很好(除了换行符),所以我猜这是可能的。我在网上找到的大部分答案在只有文本的虚拟 pdf 上工作得很好,但在地图上给出的结果特别糟糕。 例如,像这样
from tika import parser # pip install tika
raw = parser.from_file('test2.pdf')
print(raw['content'])
检索文本效果很好,但我有很多像这样的垃圾:
ERY
CTR
3
CH
A
因地图而出现
像这样的东西,它通过将 pdf 转换为图像然后读取图像来工作,面临同样的问题(我在 Whosebug 上的一个非常相似的线程上找到它,但没有答案):
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'])
你知道怎么解决吗?它可以是任何语言。 谢谢
您可以尝试的一种方法是使用能够解析 PDF 中文本字符的工具包,然后使用对象属性尝试删除不需要的地图标签,同时保留所需的文本字符。
例如,ParsePages method from 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
最后,您将不得不尝试提出一个好的标准来过滤掉不需要的文本,而不删除您需要保留的文本,使用这种方法。