python 在html中显示unicode

5 投票
4 回答
3495 浏览
提问于 2025-04-16 12:35

我正在写一个脚本,把我的链接和标题从Chrome导出到HTML文件中。
Chrome的书签是以JSON格式存储的,使用UTF编码。
有些标题是俄语的,所以它们的存储方式是这样的:
"name": "\u0425\u0430\u0431\u0440\ ..."

import codecs
f = codecs.open("chrome.json","r", "utf-8")
data = f.readlines()

urls = [] # for links
names = [] # for link titles

ind = 0

for i in data:
    if i.find('"url":') != -1:
        urls.append(i.split('"')[3])
        names.append(data[ind-2].split('"')[3])
    ind += 1

fw = codecs.open("chrome.html","w","utf-8")
fw.write("<html><body>\n")
for n in names:
    fw.write(n + '<br>')
    # print type(n) # this will return <type 'unicode'> for each url!
fw.write("</body></html>")

现在,在chrome.html中,我看到的内容显示为 \u0425\u0430\u0431...
我该如何把它们转换回俄语呢?
我使用的是Python 2.5。

**编辑:解决了!**

s = '\u041f\u0440\u0438\u0432\u0435\u0442 world!'
type(s)
<type 'str'>

print s.decode('raw-unicode-escape').encode('utf-8')
Привет world!

我需要的就是把str格式的 \u041f... 转换成unicode格式。

f = open("chrome.json", "r")
data = f.readlines()
f.close()

urls = [] # for links
names = [] # for link titles

ind = 0

for i in data:
    if i.find('"url":') != -1:
        urls.append(i.split('"')[3])
        names.append(data[ind-2].split('"')[3])
    ind += 1

fw = open("chrome.html","w")
fw.write("<html><body>\n")
for n in names:
    fw.write(n.decode('raw-unicode-escape').encode('utf-8') + '<br>')
fw.write("</body></html>")

4 个回答

0

你可以在文件开头加上utf-8的BOM,这样Chrome就知道要把它当作utf-8格式来读取,而不是ascii格式:

fw = codecs.open("chrome.html","w","utf-8")
fw.write(codecs.BOM_UTF8.decode('utf-8'))
fw.write(u'你好')

哦,不过如果你在Python中打开这个文件,记得要用 'utf-8-sig' 来去掉BOM。

也许你需要把unicode编码成utf-8,但我觉得codecs库已经帮你做了这个,对吧:

1

这是一个JSON文件,所以你应该用JSON解析器来读取它。这样你就能直接得到一个Unicode字符串,而不需要自己去处理那些转义字符。这种方法更可靠,也更简单,因为JSON字符串和Python字符串的格式其实是不一样的。

虽然它们看起来很相似,都是用\u格式,但你现在的代码在处理其他转义字符时会出问题,更别提它还依赖于JSON文件中属性的顺序和空格设置,这让它变得非常脆弱。

import json, cgi, codecs

with open('chrome.json') as fp:
    bookmarks= json.load(fp)

with codecs.open('chrome.html', 'w', 'utf-8') as fp:
    fp.write(u'<html><body>\n')
    for root in bookmarks[u'roots'].values():
        for child in root['children']:
            fp.write(u'<a href="%s">%s</a>' % (
                cgi.escape(child[u'url']),
                cgi.escape(child[u'name'])
            ))
    fp.write(u'</body></html>')

另外,要注意使用cgi.escape来对字符串中的<&字符进行HTML编码。

1

顺便说一下,不仅仅是俄语,页面名称中出现非ASCII字符的情况也很常见。举个例子:

name=u'Python Programming Language \u2013 Official Website'
url=u'http://www.python.org/'

作为一种替代方案,避免使用那种脆弱的代码,比如

urls.append(i.split('"')[3])
names.append(data[ind-2].split('"')[3])
# (1) relies on name being 2 lines before url
# (2) fails if there is a `"` in the name
# example: "name": "The \"Fubar\" website",

你可以使用json模块来处理输入文件。如果你用的是Python 2.5,可以去simplejson下载。

这里有一个模拟你代码的脚本:

try:
    import json
except ImportError: 
    import simplejson as json
import sys

def convert_file(infname, outfname):

    def explore(folder_name, folder_info):
        for child_dict in folder_info['children']:
            ctype = child_dict.get('type')
            name = child_dict.get('name')
            if ctype == 'url':
                url = child_dict.get('url')
                # print "name=%r url=%r" % (name, url)
                fw.write(name.encode('utf-8') + '<br>\n')
            elif ctype == 'folder':
                explore(name, child_dict)
            else:
                print "*** Unexpected ctype=%r ***" % ctype

    f = open(infname, 'rb')
    bmarks = json.load(f)
    f.close()
    fw = open(outfname, 'w')
    fw.write("<html><body>\n")
    for folder_name, folder_info in bmarks['roots'].iteritems():
        explore(folder_name, folder_info)
    fw.write("</body></html>")
    fw.close()    

if __name__ == "__main__":
    convert_file(sys.argv[1], sys.argv[2])

在Windows 7专业版上使用Python 2.5.4进行了测试。

撰写回答