[转4]关于HTML网页源码的字符编码(charset)格式(GB2312,GBK,UTF-8,ISO8859-1等)的解释 - rednuo

时间:2024-03-06 17:22:51

[转4]关于HTML网页源码的字符编码(charset)格式(GB2312,GBK,UTF-8,ISO8859-1等)的解释

转自:http://www.crifan.com/summary_explain_what_is_html_charset_and_common_value_of_gb2312_gbk_utf_8_iso8859_1/

 

当你通过浏览器,打开某个网站,即某个url地址的时候,你所能正常看到网页的内容,各种文字,都可以正常显示,且没有显示乱码。

此过程,涉及到,浏览器帮你正确解析HTML源码,其中涉及到HTML网页源码的字符编码处理方面的问题。

 

和html字符编码有关的流程

和字符编码处理相关的大概逻辑是:

1.浏览器访问对应的url地址,并获取对应的html(或者,以及,其他的css,javascript等)网页源码

2.浏览器识别解析HTML源码内容

其中包含了,解析html的头部(header),找到对应的charset=xxx这部分的内容,然后把根据xxx所指示的字符编码类型,去解码对应的html内容,显示对应的文字,以保证不是乱码,可以正确的显示文字信息;

 

举个例子:

当我们通过浏览器,比如IE9,去打开对应的url地址:

http://www.songtaste.com/user/351979/

时,IE9中是可以正常显示对应网页内容的:

show st url ok

而此时,内部发生的过程就是:

1.IE9去访问url地址:

http://www.songtaste.com/user/351979/

去获得对应的html源码。

2.然后解析html源码并显示

其中包括了,解析html的头部信息,找到charset=gb2312,然后用GB2312编码格式去解码,然后就可以正常显示html中的内容,确保不是乱码了。

 

如何知道HTML源码是什么编码格式的

其中,关于html中charset部分的内容,此处详细解释一下:

此处我们可以通过Notepad++去查看当前html页面的源码:

right click view source

 

然后就可以看到源码了,然后设置语言为HTML后,就可以方便看到对应的语法高亮后的源码了,其中就可以看到对应的html的header中的

1
<meta http-equiv="content-type" content="text/html;charset=gb2312">

部分的内容:

see charset is gb2312

 

注:关于Notepad++的使用,以及如何设置为默认的HTML编辑器,不熟悉的可参考:

Notepad++的默认HTML查看器

 

此处的

charset=gb2312

就是我们所要找的,html的字符编码类型。

如果我们按照此编码格式去解析html内容,就可以正常解析,不会出现乱码了。

 

注意:

1.之前就看到某处说过,有个别的html网页本身做的不规范,导致本身自己声明的是某种编码类型,但是实际上,并不全是该类型的编码,导致你去按照其所声明的编码去解析,有时候仍会出现乱码。

比如,其html中明明写的是charset=gb2312,但是实际上,其部分字符是属于GBK的,导致你按照gb2312去解码,有些字符仍会是乱码,而安装gbk去解码,就全都正常显示了,没有乱码了。

即实际上应该是charset=gbk。

对此,需要稍微注意一下。

注:关于gb2312,和gbk的关系,不了解的去看:

中文字符编码标准

 

常见的html的编码类型(即常见的html的charset的值有哪些)

国内的网站,尤其是以前建的,好像很多还是GB2312(charset=gb2312),或者是GBK(charset=gbk)

但是越来越多的,都是采用兼容性更好的,包含字符更多的UTF-8编码的了(charset=utf-8)

国外的完整,如果只是某种语言的,比如英文的,好像也有采用iso8859-1的(charset=iso8859-1),同样,更多的网站,还是采用的是utf-8的。

注:同理,关于这些字符编码类型,如果不了解,可以参考:

ISO 8859

UTF-8

总结:

  • 国内外的多数网站,都是采用charset=utf-8
  • 部分国外网站采用charset=gb2312或charset=gbk
  • 部分国外网站采用某种自己所属语言的编码,比如charset=iso8859-1

 

采用程序模拟采集并处理html源码时的注意事项

上述过程,如之前:

【整理】关于抓取网页,分析网页内容,模拟登陆网站的逻辑/流程和注意事项

所介绍的,内部逻辑都是通用的,所以可以采用工具抓取分析出来具体流程:

【教程】手把手教你如何利用工具(IE9的F12)去分析模拟登陆网站(百度首页)的内部逻辑过程

此时,接下来就是用程序模拟出来对应的流程了。

其中,就会涉及到,html源码的解析工作,涉及到html的字符编码问题。

此处,也是同理,需要通过程序,去将所获得的html源码,类似于浏览器(如IE9)一样,去按照charset所指定的编码去解码,才可以获得正常的,非乱码的内容。

 

Python语言

如我的教程:

【教程】抓取网并提取网页中所需要的信息 之 Python版

【教程】模拟登陆网站 之 Python版(内含两种版本的完整的可运行的代码)

中所给出的代码所示,Python中处理html代码的话,根据后续处理流程不同,一般可分三种:

无需关心html的编码类型

有的时候,后续对于所获得html源码,即特定字符编码的字符串,是简单的应用,比如使用正则表达式re模块,去提取某些你所想要的内容,其中只涉及到英文类字符,

此时,即使不对html解码,也是可以直接从此特定编码的字符串,即html源码中,可以查找到你要的内容的。所以就无需额外操作了,直接提起即可。

比如,

【教程】抓取网并提取网页中所需要的信息 之 Python版

中的:

1
2
3
4
5
6
#<h1 class="h1user">crifan</h1>
foundH1user = re.search(\'<h1\s+?class="h1user">(?P<h1user>.+?)</h1>\', respHtml);
print "foundH1user=",foundH1user;
if(foundH1user):
    h1user = foundH1user.group("h1user");
    print "h1user=",h1user;

 

直接从原始html中解码为对应的unicode字符串

如果是后续处理此html代码,是需要获得对应的unicode字符串,以便打印,和后续方面的提取出对应的中文等等应用,那么就需要将其解码为unicode字符串了。

类似的代码,就可以这么写了:

1
2
3
4
5
6
7
#假设当前respHtml是GBK编码类型的
htmlCharset = "GBK";
decodedUnicodeStr = respHtml.decode(htmlCharset);
#此时就已经获得了对应unicode字符串 decodedUnicodeStr 了,就可以做你要做的事情了
#比如打印出来看看
print "type(decodedUnicodeStr)=",type(decodedUnicodeStr);
print "decodedUnicodeStr=",decodedUnicodeStr;

 

使用Python第三方库去解析html时的注意事项

此处目前只介绍关于BeautifulSoup的。

详细解释参见:

【总结】Python的第三方库BeautifulSoup的使用心得

中的"当解析非UTF-8或ASCII编码类型的HTML时,需要指定对应的字符编码"

 

C#语言

C#中,此处,和上述Python,基本类似。

即,取决于你后面的应用类型,也大概分为两类:

无需关心html的编码类型

如果后续的处理html,只是提前其中英文部分的字符串之类的,那么此处实际上,也是可以不关心html编码类型的。

(对应的,所说的html代码,实际上其中的中文字符,都是乱码,但是不影响后续的英文字符串的匹配的)

举例:

【教程】抓取网并提取网页中所需要的信息 之 C#版

中的原先代码,稍作改动,就可以写出对应的完整的代码了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//step1: get html from url
string urlToCrawl = txbUrlToCrawl.Text;
//generate http request
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(urlToCrawl);
//use GET method to get url\'s html
req.Method = "GET";
//use request to get response
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
 
//string htmlCharset = "GBK";
////use songtaste\'s html\'s charset GB2312 to decode html
////otherwise will return messy code
//Encoding htmlEncoding = Encoding.GetEncoding(htmlCharset);
//StreamReader sr = new StreamReader(resp.GetResponseStream(), htmlEncoding);
 
//here not designate html charset, so Chinese char in result is messy code
StreamReader sr = new StreamReader(resp.GetResponseStream());
 
//read out the returned html
string respHtml = sr.ReadToEnd();
 
//step2: extract expected info
//<h1 class="h1user">crifan</h1>
string h1userP = @"<h1\s+class=""h1user"">(?<h1user>.+?)</h1>";
Match foundH1user = (new Regex(h1userP)).Match(respHtml);
//even though above respHtml contain messy Chinese chars, but not affect the english chars
//so follow still can found the expected english string
if (foundH1user.Success)
{
    //extracted the expected h1user\'s value
    txbExtractedInfo.Text = foundH1user.Groups["h1user"].Value;
}
else
{
    txbExtractedInfo.Text = "Not found h1 user !";
}

 

从原始html中解码为对应的unicode字符串

当想要获得对应的,无乱码的,unicode类型的html的话,则需要用到将html解码为unicode。

C#中的做法是,在使用StreamReader时,指定对应的编码类型。

完整演示代码,之前在:

【教程】抓取网并提取网页中所需要的信息 之 C#版

已经给出了,是如下的写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//step1: get html from url
string urlToCrawl = txbUrlToCrawl.Text;
//generate http request
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(urlToCrawl);
//use GET method to get url\'s html
req.Method = "GET";
//use request to get response
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
 
string htmlCharset = "GBK";
//use songtaste\'s html\'s charset GB2312 to decode html
//otherwise will return messy code
Encoding htmlEncoding = Encoding.GetEncoding(htmlCharset);
StreamReader sr = new StreamReader(resp.GetResponseStream(), htmlEncoding);
 
//read out the returned html
//here we got the, unicode (non-messy code) html
string respHtml = sr.ReadToEnd();
 
//step2: extract expected info
//<h1 class="h1user">crifan</h1>
string h1userP = @"<h1\s+class=""h1user"">(?<h1user>.+?)</h1>";
Match foundH1user = (new Regex(h1userP)).Match(respHtml);
if (foundH1user.Success)
{
    //extracted the expected h1user\'s value
    txbExtractedInfo.Text = foundH1user.Groups["h1user"].Value;
}
else
{
    txbExtractedInfo.Text = "Not found h1 user !";
}

 

【总结】

关于html的编码,最简单解释就是:

找到html源码中的charset值,按照该编码类型去解码,即可获得正确的(Unicode,非乱码的)html字符串了。