Python的urllib在网页中遇到Unicode问题

1 投票
3 回答
4747 浏览
提问于 2025-04-15 12:33

我遇到了一个常见的问题,就是如何正确读取和查看网页。看起来Python是用UTF-8格式读取网页的,但当我想把它转换成更容易查看的格式(iso-8859-1)时,就出现了错误:

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

代码大概是这样的:

#!/usr/bin/python
from urllib import urlopen
import re

url_address = 'http://www.eurohockey.net/players/show_player.cgi?serial=4722'

finished = 0
begin_record = 0
col = 0
str = ''

for line in urlopen(url_address):
    if '</tr' in line:
        begin_record = 0                   
        print str
        str = ''
        continue

    if begin_record == 1:
        col = col + 1
        tmp_match =  re.search('<td>(.+)</td>', line.strip())
        str = str + ';' + unicode(tmp_match.group(1), 'iso-8859-1')

    if '<tr class=\"even\"' in line or '<tr class=\"odd\"' in line: 
        begin_record = 1
        col = 0
        continue

我该怎么处理这些内容呢?Firefox至少认为它是iso-8859-1格式,看看那个网页的内容也确实有道理。错误明显是因为字符'ä'导致的。

如果我想把这些数据保存到数据库里,是不是就不需要改变编码,然后在显示的时候再转换呢?

3 个回答

1

那段文字确实是iso-88591-1格式的,我可以轻松解码它,而且你的代码运行得也很顺利。

不过,你的问题是编码错误,而不是解码错误。而且在你的代码中并没有进行任何编码,所以可能是你把编码和解码搞混了,这个问题很常见。

你是从Latin1解码到Unicode,而编码则是反方向的。记住,Latin1、UTF8等都被称为“编码”。

3

正如Lennart所提到的,你的问题不是解码,而是试图用“ascii”格式进行编码,这通常会在print语句中出现问题。我怀疑这一行

print str

就是你的问题所在。你需要把字符串编码成你的控制台所使用的格式,这样这一行才能正常工作。

2

看起来Python根本没有“以UTF-8读取”。正如之前提到的,你遇到的是编码问题,而不是解码问题。你说的那行代码不可能导致这个错误。当你问这样的问题时,记得提供完整的错误追踪信息和错误消息。

Kathy的怀疑是对的;实际上,print str这一行是唯一可能导致这个错误的地方,而这种情况只会在sys.stdout.encoding没有设置时发生,这时Python就会默认使用'ascii'。

可能影响结果的因素包括你使用的Python版本、你运行的操作系统,以及你具体是如何运行你的脚本的——这些你都没有告诉我们,请补充一下。

举个例子:我在Windows XP上使用Python 2.6.2,并且在你的脚本中加了一些调试信息: (1) 在开头加上import sys; print sys.stdout.encoding (2) 在print str之前加上print repr(str),这样我可以在程序崩溃之前看到你输出的内容。

在命令提示符窗口中,如果我运行\python26\python hockey.py,它会打印cp850作为编码,并且正常工作。

但是如果我这样做

\python26\python hockey.py | more

或者这样

\python26\python hockey.py >hockey.txt

它会打印None作为编码,并且在第一行出现带有变音符号的字母时崩溃,显示你的错误消息:

C:\junk>\python26\python hockey.py >hockey.txt
Traceback (most recent call last):
  File "hockey.py", line 18, in <module>
    print str
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 2: ordinal not in range(128)

如果这符合你的情况,通常的解决办法是明确地使用适合你计划使用的显示机制的编码来编码你的输出。

撰写回答