您的位置:首页 > 编程语言 > Python开发

03-网页内容的编码检测 | 02.数据解析 | Python

2010-05-18 15:57 656 查看

03-网页内容的编码检测

郑昀 201005 隶属于《02.数据解析》小节

我们需要确定网页的内容/标题等文字的编码格式,比如 utf-8 、gb2312 等。

通用检测顺序

一般来说,国内外类似服务的检测顺序是(参见参考资源A):

charset parameter in HTTP
Content-type
header.
<meta http-equiv="content-type">
element in the
<head>
of a web page for HTML documents.
encoding attribute in the XML prolog for XML documents.
Auto-detect the character encoding as a last resort.
也就是,HTTP Response 的 header 里 content-type 如果指定 charset 的话,优先级是高于 HTML 里的 content-type 的。

由于我国网络服务商不一定保持 HTTP
Content-type
header 与 meta charset 一致,比如新浪新闻、和讯、网易新闻的 html 里都会写明 meta charset 是 gb2312,但新浪新闻的 HTTP
Content-type
header 里却只输出:Content-Type: text/html ,并没有给出 charset 参数。网易新闻则 HTTP Header 中指定 GBK ,而 HTML 里却指定 GB2312 。

国外的一些服务探测我国网站时,容易因此得到乱码,如我的文章《Yahoo! Pipe的charset问题之解决方法》所说的。

这样带来的一个问题就是:

当 HTTP Content-type header 与 meta charset 不一致时,到底采信谁的声明?

当然也可以用 chardet 来检测内容,但 chardet 非常消耗资源,在网络爬虫中频繁调用 chardet 吞吐大量 html 字符串,会降低抓取效率。

BeautifulSoup 自动探测机制

BeautifulSoup 会自动判断页面编码,如果判断不出来就调用 chardet 探测。它的探测顺序是:

Beautiful Soup tries the following encodings, in order of priority, to turn your document into Unicode:

An encoding you pass in as the
fromEncoding
argument to the soup constructor.
An encoding discovered in the document itself: for instance, in an XML declaration or (for HTML documents) an
http-equiv
META tag. If Beautiful Soup finds this kind of encoding within the document, it parses the document again from the beginning and gives the new encoding a try. The only exception is if you explicitly specified an encoding, and that encoding actually worked: then it will ignore any encoding it finds in the document.
An encoding sniffed by looking at the first few bytes of the file. If an encoding is detected at this stage, it will be one of the UTF-* encodings, EBCDIC, or ASCII.
An encoding sniffed by the
chardet
library, if you have it installed.
UTF-8
Windows-1252
BeautifulSoup 优先用 meta charset 指示的编码进行探测,但未必对。

举一个异常的例子,http://www.miniclip.com/games/cn/ ,它的 HTTP Content-type header 是 utf-8,而 meta charset 却是 iso-8859-1,实际上它的编码是 utf-8 。

对于这种情况,怎么办?

可以让 BeautifulSoup 强制按照 HTTP Content-type 声明的编码做转换:

from BeautifulSoup import BeautifulSoup
from urllib import urlopen
response=urlopen('http://www.miniclip.com/games/cn/')
charset=BeautifulSoup.CHARSET_RE.search(response.headers['content-type'])
charset=charset and charset.group(3) or None
page=BeautifulSoup(response.read(),fromEncoding=charset)

参考资源:

A、 Encoding detection library in python

B、 [CPyUG:76548] 关于正确的判断页面编码

C、 Beautifulsoup 分析网页乱码问题解决办法

D、 Python中文问题研究

E、 BeautifulSoup处理gb2312编码网页的一个bug
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: