BeautifulSoup 4将HTML实体转换为unicode,但在使用print时获取垃圾字符

DaW*_*Pug 3 python unicode beautifulsoup html-entities

我正在尝试使用BeautifulSoup 4从网上抓取文本来解析它.将bs4处理过的文本打印到控制台时,我遇到了一个问题.每当我点击一个原本是HTML实体的角色时,就像’ 我在控制台上得到了垃圾字符.我相信bs4正在将这些实体正确转换为unicode,因为如果我尝试使用其他编码来打印文本,它会抱怨字符的适当缺乏unicode映射(比如u'\ u2019.)我不知道为什么打印功能对这些字符感到困惑.我已经尝试更改字体,这会改变垃圾字符,并且我在使用美国英语语言环境的Windows 7机器上.这是我的代码供参考,任何帮助表示赞赏.提前致谢!

#!/usr/bin/python
import json
import urllib2
import cookielib
import bs4

cj = cookielib.CookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))

url = "http://api.nytimes.com/svc/search/v2/articlesearch.json?q=Tiguan\
&page=0&api-key=blah"
response = opener.open(url)
articles = response.read()
decoded = json.loads(articles)

totalpages = decoded['response']['meta']['hits']/10

for page in range(totalpages + 1):
    if page>0:
        url = "http://api.nytimes.com/svc/search/v2/articlesearch.json?\
q=Tiguan&page=" + str(page) + "&api-key=blah"
        response = opener.open(url)
        articles = response.read()
        decoded = json.loads(articles)
    for url in decoded['response']['docs']:
        print url['web_url']
        urlstring = url['web_url']
        art = opener.open(urlstring)
        soup = bs4.BeautifulSoup(art.read())
        goodstuff = soup.findAll('nyt_text')
        for tag in goodstuff:
            print tag.prettify().encode("UTF")
Run Code Online (Sandbox Code Playgroud)

aba*_*ert 7

该问题与bs4,HTML实体或其他任何内容无关.在大多数Windows系统上,您可以使用单行程序重现完全相同的行为,以打印出当您尝试打印时显示为垃圾的相同字符,如下所示:

print u'\u2019'.encode('UTF-8')
Run Code Online (Sandbox Code Playgroud)

这里的问题是,像绝大多数Windows系统一样(2013年没有其他任何人使用过),你的默认字符集不是UTF-8,而是像CP1252.

因此,当您将Unicode字符串编码为UTF-8并将这些字节打印到控制台时,控制台会将它们解释为CP1252.在这种情况下,这意味着你得到’而不是.

更改字体无济于事.的UTF-8编码\u2013是3个字节\xe2,\x80\x99,和这三个字节CP1252意思是â,.

如果要手动编码控制台,则需要编码为正确的字符集,即控制台实际使用的字符集.你也许能够做到这一点sys.stdout.encoding.

当然,您可能会尝试为正确的字符集编码事物,因为像CP1252这样的8位字符集只能处理Unicode中110K字符中的大约240个字符.处理它的唯一方法是使用errors参数来encode忽略它们或用替换字符替换它们.

同时,如果你还没有读过Unicode HOWTO,你真的需要.特别是如果你打算坚持使用Python 2.x和Windows.


如果您想知道为什么一些命令行程序似乎能够解决这些问题:Microsoft的字符集问题解决方案是创建一个使用16位字符而不是8位的完整并行API集,这些API总是使用UTF-16.不幸的是,很多东西,比如微软为控制台提供的便携式stdio包装器以及Python 2.x所依赖的,只有8位API.这意味着问题根本没有解决.Python 3.x不再使用这些包装器,并且一直在讨论如何将未来版本的UTF-16与控制台进行对话.但即使这种情况发生在3.4(这似乎不太可能),只要您使用2.x,这对您无济于事.