Python Camelot PDF - Windows 使用 Stream flavor 时出现 UnicodeEncodeError

Python Camelot PDF - UnicodeEncodeError when using Stream flavor, on Windows

Python 3.7 on Windows 10. 柯莱特 0.8.2

我正在使用以下代码将 pdf 文件转换为 HTML:

import camelot
import os
 
def CustomScript(args):
    path_to_pdf = "C:\PDFfolder\abc.pdf"        
    folder_to_pdf = os.path.dirname(path_to_pdf)
    tables = camelot.read_pdf(os.path.normpath(path_to_pdf), flavor='stream', pages='1-end')
    tables.export(os.path.normpath(os.path.join(folder_to_pdf,"temp","foo.html")), f='html')
    return CustomScriptReturn.Empty();

我在 tables.export 行收到以下错误:

"UnicodeEncodeError -'charmap' codec can't encode character '\u2010' in position y: character maps to undefined.

此代码 运行s 在 Mac 上没有问题。此错误似乎与 Windows 有关,这是我需要 运行 的环境。

我现在已经花了整整两天时间研究这个错误 令人作呕 - 我已经尝试了 Stack Overflow 上提供的许多解决方案,这些解决方案来自几个 post 相关对此。错误仍然存​​在。添加所有解决方案中建议的代码行的问题在于,它们都是要添加到普通 Python 方法的参数。这些参数不适用于 Camelot 的 export 方法。

编辑 1: 更新了 post 以指定哪一行引发错误。

编辑 2: 使用的 PDF 文件:http://tsbde.texas.gov/78i8ljhbj/Fiscal-Year-2014-Disciplinary-Actions.pdf

编辑 3: 这是来自 Windows 控制台的完整回溯:

> Traceback (most recent call last):   File "main.py", line 18, in
> <module>
>     tables.export(os.path.normpath(os.path.join(folder_to_pdf, "foo.html")), f='html')   File
> "C:\Users\stpete\AppData\Local\Programs\Python\Python37\lib\site-packages\camelot\core.py",
> line 737, in export
>     self._write_file(f=f, **kwargs)   File "C:\Users\stpete\AppData\Local\Programs\Python\Python37\lib\site-packages\camelot\core.py",
> line 699, in _write_file
>     to_format(filepath)   File "C:\Users\stpete\AppData\Local\Programs\Python\Python37\lib\site-packages\camelot\core.py",
> line 636, in to_html
>     f.write(html_string)   File "C:\Users\stpete\AppData\Local\Programs\Python\Python37\lib\encodings\cp1252.py",
> line 19, in encode
>     return codecs.charmap_encode(input,self.errors,encoding_table)[0] UnicodeEncodeError: 'charmap' codec can't encode character '\u2010' in
> position 5737: character maps to <undefined>

您得到 UnicodeEncodeError,在这种情况下,这意味着要写入文件的输出包含一个无法使用您平台的默认编码 cp1252 进行编码的字符。

writing to an html file.

时,camelot 似乎无法处理设置编码

解决方法可能是在 运行 您的程序:

时将 PYTHONIOENCODING 环境变量设置为“UTF-8”
C:\> set PYTHONIOENCODING=UTF-8 && python myprog.py 

强制使用 UTF-8 编码输出文件。

您遇到的问题与方法有关camelot.core.Table.to_html:

def to_html(self, path, **kwargs):
"""Writes Table to an HTML file.
For kwargs, check :meth:`pandas.DataFrame.to_html`.
Parameters
----------
path : str
    Output filepath.
"""
html_string = self.df.to_html(**kwargs)
with open(path, "w") as f:
    f.write(html_string)

这里要写入的文件应该是UTF-8编码打开的,不是。

这是我的解决方案,它使用猴子补丁替换原来的 camelot 方法:

import camelot
import os

# here I define the corrected method
def to_html(self, path, **kwargs):
    """Writes Table to an HTML file.
    For kwargs, check :meth:`pandas.DataFrame.to_html`.
    Parameters
    ----------
    path : str
        Output filepath.
    """
    html_string = self.df.to_html(**kwargs)
    with open(path, "w", encoding="utf-8") as f:
        f.write(html_string)

# monkey patch: I replace the original method with the corrected one
camelot.core.Table.to_html=to_html

def CustomScript(args):
    path_to_pdf = "C:\PDFfolder\abc.pdf"        
    folder_to_pdf = os.path.dirname(path_to_pdf)
    tables = camelot.read_pdf(os.path.normpath(path_to_pdf), flavor='stream', pages='1-end')
    tables.export(os.path.normpath(os.path.join(folder_to_pdf,"temp","foo.html")), f='html')
    return CustomScriptReturn.Empty();

我测试了这个解决方案,它适用于 Python 3.7、Windows 10、Camelot 0.8.2。