将 io.BytesIO 转换为 io.StringIO 以解析 HTML 页面

Posted

技术标签:

【中文标题】将 io.BytesIO 转换为 io.StringIO 以解析 HTML 页面【英文标题】:Convert io.BytesIO to io.StringIO to parse HTML page 【发布时间】:2014-08-25 08:10:21 【问题描述】:

我正在尝试解析通过 pyCurl 检索到的 html 页面,但 pyCurl WRITEFUNCTION 将页面返回为 BYTES 而不是字符串,因此我无法使用 BeautifulSoup 解析它。

有没有办法将 io.BytesIO 转换为 io.StringIO?

或者有没有其他方法可以解析 HTML 页面?

我正在使用 Python 3.3.2。

【问题讨论】:

用尽BytesIO 然后从输出构造StringIO 的幼稚方法不满足您的约束吗? 【参考方案1】:

接受的答案中的代码实际上完全从流中读取以进行解码。下面是正确的方法,将一个流转换为另一个流,可以逐块读取数据。

# Initialize a read buffer
input = io.BytesIO(
    b'Inital value for read buffer with unicode characters ' +
    'ÁÇÊ'.encode('utf-8')
)
wrapper = io.TextIOWrapper(input, encoding='utf-8')

# Read from the buffer
print(wrapper.read())

【讨论】:

能否添加一个逐块读取的示例? @AlexeiMarinichenko 您可以阅读有关 TextIOWrapper 方法的文档。试试wrapper.read(5)wrapper.realine()【参考方案2】:

一种天真的方法:

# assume bytes_io is a `BytesIO` object
byte_str = bytes_io.read()

# Convert to a "unicode" object
text_obj = byte_str.decode('UTF-8')  # Or use the encoding you expect

# Use text_obj how you see fit!
# io.StringIO(text_obj) will get you to a StringIO object if that's what you need

【讨论】:

谢谢,它确实有效。但是我使用 bytes_io.getvalue() 而不是 bytes_io.read() 因为前者不起作用。 啊,是的,我假设您的 BytesIO 位于流的开头。 getvalue我相信无论你在哪里都应该工作:) 通常你必须在 read() 调用之前调用bytes_io.seek(0)。正如@AnthonySottile 提到的,getvalue 解决了这个问题。 似乎效率很低 - 我们需要将所有文件加载到内存中以进行解码。这应该适用于小文件,但不适用于大文件。 当前的两个答案都效率低下——我可能会用增量解码器答案来更新它,但在这一点上它真的不值得我努力

以上是关于将 io.BytesIO 转换为 io.StringIO 以解析 HTML 页面的主要内容,如果未能解决你的问题,请参考以下文章

在 python3.6 中从“_io.BytesIO”转换为类似字节的对象?

使用 io.BytesIO 从天蓝色存储读取图像?

PIL(Pillow)的学习笔记

在 python3 中写入 csv 中的 io.BytesIO 失败

如何将Pandas DataFrame转换为类似字节的对象

使用 Avro 将对象编码为 Python 中的字节数组