2

我正在使用 GAE 和 Python 从各个站点抓取新闻文章。

我一次抓取一篇文章网址的代码导致以下错误:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 8858: ordinal not in range(128)

这是我最简单形式的代码:

from google.appengine.api import urlfetch

def fetch(url):
    headers = {'User-Agent' : "Chrome/11.0.696.16"}
    result = urlfetch.fetch(url,headers)
    if result.status_code == 200:
        return result.content

这是我尝试过的另一个变体,结果相同:

def fetch(url):
    headers = {'User-Agent' : "Chrome/11.0.696.16"}
    result = urlfetch.fetch(url,headers)
    if result.status_code == 200:
        s = result.content
        s = s.decode('utf-8')
        s = s.encode('utf-8')
        s = unicode(s,'utf-8')
        return s

这是丑陋的,脆弱的,它也不起作用:

def fetch(url):
    headers = {'User-Agent' : "Chrome/11.0.696.16"}
    result = urlfetch.fetch(url,headers)
    if result.status_code == 200:
        s = result.content

        try:
            s = s.decode('iso-8859-1')
        except:
            pass
        try:
            s = s.decode('ascii')
        except: 
            pass
        try:
            s = s.decode('GB2312')
        except:
            pass
        try:
            s = s.decode('Windows-1251')
        except:
            pass
        try:
            s = s.decode('Windows-1252')
        except:
            s = "did not work"

        s = s.encode('utf-8')
        s = unicode(s,'utf-8')
        return s

最后一个变体从最后一个异常返回 s 作为字符串“没有工作”。

那么,我是否将不得不扩展我笨拙的 try/except 构造以包含所有可能的编码(甚至可以工作吗?),还是有更简单的方法?

为什么我决定抓取整个 html,而不仅仅是 BeautifulSoup?因为我想稍后再做优化,以避免 GAE 中的 DeadlineExceedError。

我是否阅读了所有关于 Unicode 的优秀文章,以及应该如何做?是的。但是,我找不到一个不假设我知道传入编码的解决方案,而我不知道,因为我每天都在抓取不同的站点。

4

2 回答 2

2

前段时间我遇到了同样的问题,没有什么是 100% 准确的。我所做的是:

  • 从 Content-Type 获取编码
  • 从元标记获取编码
  • 使用 chardet Python 模块检测编码
  • 将文本从最常见的编码解码为 Unicode
  • 处理文本/html
于 2013-08-15T23:11:48.103 回答
1

最好在元标记或标题中简单地读取 Content-Type。请注意,Chrome(与 Opera 相对)不会猜测编码。如果在任何一个地方都没有说它是 UTF8 或其他任何东西,它会将站点作为 Windows 默认编码进行处理。所以只有非常糟糕的网站才不会定义它。

于 2013-08-15T22:49:34.420 回答