03-网页内容的编码检测 | 02.数据解析 | Python
03-网页内容的编码检测郑昀 201005隶属于《02.数据解析》小节
我们需要确定网页的内容/标题等文字的编码格式,比如 utf-8 、gb2312 等。
通用检测顺序
一般来说,国内外类似服务的检测顺序是(参见参考资源A):
[*]charset parameter in HTTP Content-type header.
[*] element in the 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,但新浪新闻的 HTTPContent-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 turnyour document into Unicode:
[*]An encoding you pass in as the fromEncoding argument to thesoup constructor.
[*]An encoding discovered in the document itself: for instance, in an XMLdeclaration or (for HTML documents) an http-equiv META tag. IfBeautiful Soup finds this kind of encoding within the document, it parses thedocument again from the beginning and gives the new encoding a try. The onlyexception is if you explicitly specified an encoding, and that encoding actuallyworked: 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 anencoding is detected at this stage, it will be one of the UTF-* encodings,EBCDIC, or ASCII.
[*]An encoding sniffed by the chardet library, if youhave 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 urllibimport 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、 Encodingdetection library in python ;
B、 关于正确的判断页面编码 ;
C、 Beautifulsoup分析网页乱码问题解决办法 ;
D、 Python中文问题研究 ;
E、 BeautifulSoup处理gb2312编码网页的一个bug ;
页:
[1]