【问题标题】:How to fix encoding error when Python writes to HTMLPython写入HTML时如何修复编码错误
【发布时间】:2019-06-27 02:19:41
【问题描述】:

我使用 Python 3.7 和 Beautifulsoup 创建了一个网络解析器。然后,我使用“find_all”查找具有某个类的所有标签。重要的是我正在抓取的网站有一些汉字。这是我的代码:

import requests
from bs4 import BeautifulSoup

response = requests.get('URL_GOES_HERE')
soup = BeautifulSoup(response.content, 'html.parser')
posts = soup.find_all(class_='CLASS_GOES_HERE')

print(posts)

saveFile = open('index.html','w+')
saveFile.write(str(posts))
saveFile.close()

我尝试以两种不同的方式输出数据:将数据打印到控制台,以及将其写入 HTML 文档。我分别做了每一个,通过在写入 HTML 时“注释掉”打印功能,反之亦然。

当我只运行打印功能时,它会很好地将数据输出到控制台上,没有任何错误。但是,当我运行函数写入 HTML 时,出现以下编码错误:

Traceback (most recent call last):
  File "postthis.py", line 11, in <module>
    saveFile.write(str(posts))
  File "C:\Users\atit1\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 characters in position 4308-4324: character maps to <undefined>"

过去 2 天我一直在尝试使用 Stackoverflow 上许多类似问题的指导来解决此问题。许多答案建议添加“.encode(“utf-8”)”,所以我尝试了。例如,当我尝试 .write(str(soup)) 时,我得到了编码错误。但是当我写这个时,它完美地工作:

saveFile.write(str(soup.encode("utf-8")))

但是,问题在于这会将网站的整个 HTML 文档打印到我的 HTML 文档中,而我只希望它编写一些类。从逻辑上讲(呃,也许不是?),然后我尝试将 .encode 添加到我的帖子变量中,如下所示:

saveFile.write(str(posts.encode("utf-8")))

但是我一直遇到这个错误,我不知道为什么:

Traceback (most recent call last):
  File "webscraper.py", line 21, in <module>
    saveFile.write(str(posts.encode("utf-8")))
  File "C:\Users\atit1\AppData\Local\Programs\Python\Python37\lib\site-packages\bs4\element.py", line 1620, in __getattr__
    "ResultSet object has no attribute '%s'. You're probably treating a list of items like a single item. Did you call find_all() when you meant to call find()?" % key
AttributeError: ResultSet object has no attribute 'encode'. You're probably treating a list of items like a single item. Did you
call find_all() when you meant to call find()?

有人对如何修复此错误有一些建议吗?顺便说一句,我只需要网站上的英文文本,所以如果你的解决方案会省略/损坏特殊的汉字,那没关系。

EDIT 1 这是我试图解析的 HTML 源代码的一部分。这些列表中大约有 50 个,其中一些包含外国名称,所以当我尝试解析它时遇到编码错误。

<li>
    <div itemscope="SOME_WORDS" itemid="SOME_URL" itemtype="SOME_URL">\

        <meta itemprop="url" content="SOME_URL"/>
        <a class="THE_CLASS_I_WANT"  href="THE_URL_I_WANT">

            <span itemprop="SOME_WORDS">
                THE TEXT I WANT 
            </span>
        </a> 

    </div>      
</li>   

【问题讨论】:

  • 添加二进制选项,open('index.html','wb+')有什么区别?
  • @StanS。谢谢回复。这样做时我收到同样的错误。但是,当我删除 str 部分并运行它时,我收到此错误:“TypeError: a bytes-like object is required, not 'ResultSet'”。
  • 没有看到您正在解析的内容,很难为您提供帮助。您是否尝试过错误输出中提到的建议(例如,将find_all 更改为find)?另外,您为什么还要尝试encode 输出呢?它应该已经正确编码,所以没有必要。
  • @l'L'l 嗨,我编辑了我的帖子以添加我正在解析的内容(除了我删除了 URL 和单词,因为它是我朋友业务的一部分)。将 find_all 更改为 find 并不是很有帮助,而且这样做时我遇到了更多错误。另外,我正在尝试对输出进行编码,因为当我不这样做时,我会收到该编码错误,并且 Stackoverflow 上的一些答案建议我们添加 .encode 以摆脱它,但由于某种原因它不起作用。跨度>

标签: python html parsing encoding beautifulsoup


【解决方案1】:

您正在尝试调用posts.encode() 方法,该方法没有。 postsfind_all() 返回 - 假设您真的想找到所有这些,您必须分别对所有找到的元素进行编码。

此外,您可能希望创建一个有效的 html 文档,而不是将整个帖子列表作为列表写入文件,这完全是另一个问题。

做你正在做的事(尽管我认为这不会是你最终想要的):

saveFile = open('index.html','w+')
saveFile.write(str([post.encode('utf-8') for post in posts]))
saveFile.close()

或者,可能会好一点,但可能仍然不是您可能需要的结果:

saveFile = open('index.html','wb+')
for post in posts:
    saveFile.write(post.encode('utf-8'))
saveFile.close()

注意重要的区别:不是仅仅编写整个列表的字符串转换,而是单独编码每个元素,并将生成的 bytes 写入已使用 @987654328 以二进制(而非文本)模式打开的文件@。

【讨论】:

  • 嘿,非常感谢朋友,第一行没有用,但第二行用了!非常感谢,我花了很多时间在这上面!! :)
  • 很高兴它对您有用。您可能需要做更多的工作以使 index.html 成为一个实际有效的 html 文档,但很可能您不需要它不仅仅是所选元素的组合。
猜你喜欢
  • 2020-03-06
  • 2019-11-12
  • 1970-01-01
  • 1970-01-01
  • 2019-12-09
  • 1970-01-01
  • 2022-07-26
  • 2013-08-16
  • 1970-01-01
相关资源
最近更新 更多