最近论坛助手项目遇到需要好获取论坛源码的问题,而不同的论坛可能采用不用的编码方式,因此如果采用统一的编码来获取论坛源码,那么获得的源码很有可能是乱码,所以需要先知道论坛HTML源码的编码方式,然后再按该编码方式获取源码。
根据网上的资料,使用WebClient来获取源码,很容易就能得到网页源码。在C#里,提供了丰富的工具类库,可以轻松的转码。但是,却发现不能自动获取网站上的字符编码而自动正确的解释源码,而导致汉字显示乱码。同样,在JAVA的各种获取网站源码的类库里,也不能自动根据网页字符编码自动正确解释编码,只能我们自己手动来做了。
我的解决办法是先采用系统默认的编码从 stream里得到源码,再使用正则表达式获取源码中的[获取网页字符编码描述信息],这个信息,一般来说,网页里都会有的,在网页源码的<head>里,类似这样的代码:<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />(其实不一样完全这样,有些不规范的,没有双引号,或者最后面没有/闭合,所以,正则表达式得考虑周全些),从这个代码里来获取编码信息,再用网页中获取到得编码来重新从stream里解释取得网页源码。
源码如下:
public string getContent(Uri uri, CookieContainer cc)
{
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(uri);
myRequest.CookieContainer = cc;
WebResponse response = myRequest.GetResponse();
Stream streamIn = response.GetResponseStream();
StreamReader reader = new StreamReader(streamIn, Encoding.Default);//Encoding.GetEncoding("GBK")
string stringResponse = reader.ReadToEnd();
Match charSetMatch = Regex.Match(stringResponse, "<meta([^<]*)charset=([^<]*)/"", RegexOptions.IgnoreCase | RegexOptions.Multiline);
string charSet = charSetMatch.Groups[2].Value;
charSet = charSet.ToUpper();
myRequest = (HttpWebRequest)WebRequest.Create(uri);
myRequest.CookieContainer = cc;
response = myRequest.GetResponse();
streamIn = response.GetResponseStream();
switch (charSet)
{
case "UTF-8":
reader = new StreamReader(streamIn, Encoding.UTF8);
break;
case "GBK":
reader = new StreamReader(streamIn, Encoding.GetEncoding("GBK"));
break;
case "BIG5":
reader = new StreamReader(streamIn, Encoding.GetEncoding("BIG5"));
break;
case "GB2312":
reader = new StreamReader(streamIn, Encoding.GetEncoding("GB2312"));
break;
}
stringResponse = reader.ReadToEnd();
reader.Close();
streamIn.Close();
response.Close();
return stringResponse;
}
先用系统默认的编码获取论坛HTML源码,StreamReader的第二个参数设置为Encoding.Default,此时获得的源码可能包含乱码,但是<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />这个代码可以正确解析,因此可以通过正规式获得该网页的编码方式,正规式编写如下"<meta([^<]*)charset=([^<]*)/""(/为转义符),获得正确编码后再重复以上步骤,只是将StreamReader的第二个参数设置成刚获得的编码方式,然后就可以获得正确的编码方式了。
PS:代码部分参考网上