如何将文本 pdf 更改为 utf-8 编码?
How to change a texted pdf to utf-8 encoding?
我有一堆可以正确显示西里尔文的 pdf。但是如果我从他们那里复制和粘贴文本,就会产生乱码。
然后我使用okular的另存为功能将pdf转换为文本文件,发现编码是WINDOWS-1251,这是一个旧的西里尔编码。转换为UTF-8后,西里尔字母可以正常显示了。
文件的样本 link 是 https://cdn.esis.edu.mn/cover/01/01_mongol_khel.pdf
有没有办法将 pdf 转换为 UTF-8 编码以便我可以复制、粘贴和搜索?
已解决:
根据@iPDFdev提供的信息,我设法解决了这个问题。
对于可能遇到类似问题的任何人,我在 https://www.compart.com/en/unicode/charsets/windows-1251, and modified the code at https://github.com/pymupdf/PyMuPDF/issues/530 处将 Windows-1251 转为 UTF-8 table。我完全忽略了旧的 Unicode 映射,并为所有页面上的所有字体添加了西里尔字母映射。
import fitz
import re
doc = fitz.open(inputFileName)
new = '1 beginbfrange\n<c0> <ff> <0410>\nendbfrange'
for pno in range(doc.page_count):
font_tuples = doc.get_page_fonts(2)
for font_tuple in font_tuples:
for line in doc.xref_object(font_tuple[0]).splitlines():
line = line.strip()
if line.startswith("/ToUnicode"):
stream_id = int(line.split()[1])
old_stream_decoded = doc.xref_stream(stream_id).decode()
new_stream_decoded = re.sub('[0-9]+? beginbfrange.*endbfrange', new, old_stream_decoded, flags=re.DOTALL)
new_stream_encoded = new_stream_decoded.encode()
doc.update_stream(stream_id, new_stream_encoded)
doc.save(outputFileName)
可以使用 Windows 1251 编码将 CID(字符 ID)正确(手动)转换为西里尔文。
但是 PDF 不支持这种编码,并且字体上的 ToUnicode cmap 构建不正确。当它应该使用 Unicode 值时,它还假定 Windows-1251 编码。
例如:CID 0xCC用于显示西里尔大写字母EM(U+041C)。内部字体编码将 0xCC 映射到表示 U+041C 的字形(字符图像),因此在视觉上您可以得到正确的字母。
但是对于文本提取,您必须提供一个 ToUnicode cmap,它告诉每个 id 代表什么 Unicode 字符。所以 ToUnicode cmap 应该包含这样的条目 0xCC -> U+041C 但文件中的 ToUnicode cmap 包含此条目 0xCC -> U+00CC 这不是西里尔大写字母 EM.
顺便说一句,0xCC 使用 Windows 1251 编码映射到 U+041C,但 PDF 处理器无法知道这一点。
正在使用
poppler-22.04.0\Library\bin>pdftotext -layout -f 1 -l 1 -enc ISO-8859-9 encoded.pdf -
响应,仅布局的第一页尝试似乎表明存在一些编码问题,但它是一个粗略的程序输出,也许可以通过 FnR 或代码调整来改进
Ш.Оунццг, Є.Хадаа,
Д.Цогзолмаа, Т.нхтуяа
МОНГОЛ ХЛ
I
Еєнхий боловсолын сугуулийн
1 дїг ангийн суах бичиг
Боловсол, ол, Шинжлх Ухаан, отын амны
зєвшєєлєє хвлв.
Долоо дах хвлл
УГУУЛИЙН НОМЫН АНД ОЛГОВ.
БОЛУУЛАХЫГ ХОИГЛОНО.
Улаанбаата хот
2020 он
备选方案是尝试将此作为更有效的字符,但需要“de-spacing”
pdftotext -layout -f 1 -l 1 -enc UTF-16 encoded.pdf -
Ш . О ю у н ц э ц э г , Є . Х а д а а ,
Д . Ц о г з о л м а а , Т . Э н х т у я а
М О Н Г О Л Х Э Л
I
Е р є н х и й б о л о в с р о л ы н с у р г у у л и й н
1 д ї г э э р а н г и й н с у р а х б и ч и г
Б о л о в с р о л , ! оQ л , Ш и н ж л э х У х а а н , !? о р т ы н / а м н ы
з є в ш є є р л є є р х э в л э в .
Д о л о о д а хL х э в л э л
! У Р Г У У Л И Й Н Н О М Ы Н ! А Н Д О Л Г О В .
Б О Р Л У У Л А Х Ы Г Х О Р И Г Л О Н О .
У л а а н б а а т а р х о т
2 0 2 0 о н
De-spaced 但仍然需要将 �!
替换为 C
并将 �/
替换为 Я
等
注意两种情况下 chcp 1251
我有一堆可以正确显示西里尔文的 pdf。但是如果我从他们那里复制和粘贴文本,就会产生乱码。
然后我使用okular的另存为功能将pdf转换为文本文件,发现编码是WINDOWS-1251,这是一个旧的西里尔编码。转换为UTF-8后,西里尔字母可以正常显示了。
文件的样本 link 是 https://cdn.esis.edu.mn/cover/01/01_mongol_khel.pdf
有没有办法将 pdf 转换为 UTF-8 编码以便我可以复制、粘贴和搜索?
已解决:
根据@iPDFdev提供的信息,我设法解决了这个问题。
对于可能遇到类似问题的任何人,我在 https://www.compart.com/en/unicode/charsets/windows-1251, and modified the code at https://github.com/pymupdf/PyMuPDF/issues/530 处将 Windows-1251 转为 UTF-8 table。我完全忽略了旧的 Unicode 映射,并为所有页面上的所有字体添加了西里尔字母映射。
import fitz
import re
doc = fitz.open(inputFileName)
new = '1 beginbfrange\n<c0> <ff> <0410>\nendbfrange'
for pno in range(doc.page_count):
font_tuples = doc.get_page_fonts(2)
for font_tuple in font_tuples:
for line in doc.xref_object(font_tuple[0]).splitlines():
line = line.strip()
if line.startswith("/ToUnicode"):
stream_id = int(line.split()[1])
old_stream_decoded = doc.xref_stream(stream_id).decode()
new_stream_decoded = re.sub('[0-9]+? beginbfrange.*endbfrange', new, old_stream_decoded, flags=re.DOTALL)
new_stream_encoded = new_stream_decoded.encode()
doc.update_stream(stream_id, new_stream_encoded)
doc.save(outputFileName)
可以使用 Windows 1251 编码将 CID(字符 ID)正确(手动)转换为西里尔文。
但是 PDF 不支持这种编码,并且字体上的 ToUnicode cmap 构建不正确。当它应该使用 Unicode 值时,它还假定 Windows-1251 编码。
例如:CID 0xCC用于显示西里尔大写字母EM(U+041C)。内部字体编码将 0xCC 映射到表示 U+041C 的字形(字符图像),因此在视觉上您可以得到正确的字母。
但是对于文本提取,您必须提供一个 ToUnicode cmap,它告诉每个 id 代表什么 Unicode 字符。所以 ToUnicode cmap 应该包含这样的条目 0xCC -> U+041C 但文件中的 ToUnicode cmap 包含此条目 0xCC -> U+00CC 这不是西里尔大写字母 EM.
顺便说一句,0xCC 使用 Windows 1251 编码映射到 U+041C,但 PDF 处理器无法知道这一点。
正在使用
poppler-22.04.0\Library\bin>pdftotext -layout -f 1 -l 1 -enc ISO-8859-9 encoded.pdf -
响应,仅布局的第一页尝试似乎表明存在一些编码问题,但它是一个粗略的程序输出,也许可以通过 FnR 或代码调整来改进
Ш.Оунццг, Є.Хадаа,
Д.Цогзолмаа, Т.нхтуяа
МОНГОЛ ХЛ
I
Еєнхий боловсолын сугуулийн
1 дїг ангийн суах бичиг
Боловсол, ол, Шинжлх Ухаан, отын амны
зєвшєєлєє хвлв.
Долоо дах хвлл
УГУУЛИЙН НОМЫН АНД ОЛГОВ.
БОЛУУЛАХЫГ ХОИГЛОНО.
Улаанбаата хот
2020 он
备选方案是尝试将此作为更有效的字符,但需要“de-spacing”
pdftotext -layout -f 1 -l 1 -enc UTF-16 encoded.pdf -
Ш . О ю у н ц э ц э г , Є . Х а д а а ,
Д . Ц о г з о л м а а , Т . Э н х т у я а
М О Н Г О Л Х Э Л
I
Е р є н х и й б о л о в с р о л ы н с у р г у у л и й н
1 д ї г э э р а н г и й н с у р а х б и ч и г
Б о л о в с р о л , ! оQ л , Ш и н ж л э х У х а а н , !? о р т ы н / а м н ы
з є в ш є є р л є є р х э в л э в .
Д о л о о д а хL х э в л э л
! У Р Г У У Л И Й Н Н О М Ы Н ! А Н Д О Л Г О В .
Б О Р Л У У Л А Х Ы Г Х О Р И Г Л О Н О .
У л а а н б а а т а р х о т
2 0 2 0 о н
De-spaced 但仍然需要将 �!
替换为 C
并将 �/
替换为 Я
等
注意两种情况下 chcp 1251