抓网页时如何处理未知编码?

时间:2013-08-15 22:45:50

标签: python google-app-engine unicode

我正在使用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作为字符串“不起作用”,从最后一个除外。

所以,我是否必须扩展我的笨拙尝试/除了构造以包含所有可能的编码(甚至可以工作吗?),还是有更简单的方法?

为什么我决定刮掉整个HTML,而不仅仅是BeautifulSoup?因为我想稍后做汤,以避免GAE中的DeadlineExceedError。

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

2 个答案:

答案 0 :(得分:2)

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

  • 从Content-Type
  • 获取编码
  • 从元标记获取编码
  • 使用chardet Python模块检测编码
  • 将文本从最常见的编码解码为Unicode
  • 处理text / html

答案 1 :(得分:1)

最好只读取元标记或标题中的Content-Type。请注意,Chrome(与Opera相反)不会猜测编码。如果没有说它是UTF8或其中任何一个地方的任何其他东西,它将网站线程作为默认编码的窗口。所以只有非常糟糕的网站才能定义它。