【问题标题】:How to know what's the right encode?如何知道什么是正确的编码?
【发布时间】:2016-01-24 12:01:16
【问题描述】:

我决定学习 C++,我真的很喜欢 www.learncpp.com 这个网站。 现在,我想制作它的 pdf 版本并打印出来,以便我可以在纸上阅读。首先,我为站点中的所有章节构建了一个 url-collector。它工作正常。

现在我正在从first chapter 创建一个html。我写了以下内容:

import requests
from bs4 import BeautifulSoup
import codecs

req = requests.get("http://www.learncpp.com/cpp-tutorial/01-introduction-to-these-tutorials/")
soup = BeautifulSoup(req.text,'lxml')

content = soup.find("div", class_="post-9")

f = open("first_lesson.html","w")
f.write(content.prettify().encode('utf-8'))
f.close()

我在文件夹中找到了我的 first_lesson.html 文件。 问题是当我打开html文件查看结果时,到处都有奇怪的符号(尝试运行代码看看)。

我添加了.encode('utf-8'),否则我会收到错误消息:

UnicodeEncodeError: 'ascii' codec can't encode character u'\u2014' in position 155: ordinal not in range(128)

如何消除那些奇怪的符号?什么是正确的编码? 而且,如果我以后遇到类似的问题,我怎么知道什么是正确的编码?

更新:我没有在“utf-8”中编码,而是在“windows-1252”中编码并且它有效。但是,了解如何正确编码的最佳策略是什么?因为我不认为 try-this-try-that 是一个好方法

【问题讨论】:

  • 为什么不scrapy.org ?它专为此类任务而开发。
  • @CodePainters、req 和 bs4 是我被教导刮的第一种方法。我乐于学习新方法(我肯定想看看 scrapy),但现在我想了解为什么这不起作用

标签: python python-2.7 encoding web-scraping


【解决方案1】:

在python2中使用请求你应该使用.content来让请求处理编码,你可以使用io.open来写入文件:

import requests
from bs4 import BeautifulSoup
import io


req = requests.get("http://www.learncpp.com/cpp-tutorial/01-introduction-to-these-tutorials/")
soup = BeautifulSoup(req.content, 'lxml')
content = soup.find("div", class_="post-9")

with io.open("first_lesson.html", "w") as f:
    f.write(soup.prettify())

如果你确实想指定编码,prettify 需要一个编码参数soup.prettify(encoding=...),还有 encoding 属性:

enc = req.encoding

你可以尝试用cgi.parse_headers解析头部:

import cgi

enc = cgi.parse_header(req.headers.get('content-type', ""))[1]["charset"]

或者尝试安装和使用chardet模块:

import chardet

enc = chardet.detect(req.content)

您还应该知道,许多编码可能会在没有错误的情况下运行,但最终会在文件中出现垃圾。字符集设置为 utf-8,您可以在返回的标头中看到它,如果您查看源代码,您可以看到 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

【讨论】:

    【解决方案2】:

    content.prettify() 是一个 unicode 字符串。碰巧它包含映射到字符(EM DASH)的代码点 U+2014。 ASCII 编解码器无法对其进行编码,因为 8212=0x2014 大于 127。

    但是,您可以使用任何可以处理 unicode 代码点的编码对您的 unicode 字符串进行编码,例如 utf-16、utf-32、ucs-2、ucs-4 或 ucs-8。没有“正确”的编码,但是 utf-8 是其中之王,所以当你想编码一个 unicode 字符串时,它通常是一个不错的选择,但你可以选择另一个(python 支持的)和 例如,您的程序也可以与

    一起使用
    f.write(content.prettify().encode('utf-16'))
    

    prettify 为您提供一个 unicode 字符串,默认情况下尝试使用 utf-8 进行解码(这是我从查看源代码中了解到的),但您可以为 prettify 提供一个显式编码以用作争论。将 unicode 字符串视为一种抽象,一系列 unicode 代码点,基本上对应于一系列字符(只不过是小图像)。

    如果您需要使用 beautifulsoup 查找 HTML 文档的内容类型,您可能会发现 thisthis 问题很有用。

    另外一点:一般来说,当你有纯字节并且没有人告诉你应该如何解码它们时,你就很不走运,不得不玩whack-a-mole。如果您知道您正在处理文本,那么 utf-8 通常是一个很好的初步猜测,因为它 a) 被广泛使用,并且 b) 前 128 个 unicode 字符与 ASCII 一对一对应,而 utf-8 用相同的字节值。

    您可能还会发现来自 PyCon 2012 的 this chartablethis 谈话很有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-24
      • 2019-07-15
      • 1970-01-01
      • 2018-11-24
      • 2012-10-07
      • 2021-03-09
      • 2012-10-15
      相关资源
      最近更新 更多