在開發網站統計模組時,從 Referrer URL 提取搜尋關鍵字面臨編碼難題:Google 使用 UTF-8,百度、網易等國內引擎多用 GB2312,直接使用 Uri.UnescapeDataString() 會導致解碼錯誤。本文提供完整的自動偵測與轉碼方案。
URL 編碼的關鍵字字串本身不攜帶編碼資訊,必須根據搜尋引擎域名判斷其編碼格式,再套用正確解碼方式。UTF-8 每字元 3 位元組,GB2312 每字元 2 位元組,若混用會產生亂碼或例外。
Uri.UnescapeDataString;GB2312 先將 %XX%XX 解析為位元組陣列,再用 Encoding.Convert 轉為 UTF-8 位元組,最後解碼為字串。public class ExJudgeSystem
{
private string[][] _Enginers = new string[][] {
new string[]{"google","utf8","q"}, new string[]{"baidu","gb2312","wd"},
new string[]{"yahoo","utf8","p"}, new string[]{"yisou","utf8","search"},
new string[]{"live","utf8","q"}, new string[]{"tom","gb2312","word"},
new string[]{"163","gb2312","q"}, new string[]{"iask","gb2312","k"},
new string[]{"soso","gb2312","w"}, new string[]{"sogou","gb2312","query"},
new string[]{"zhongsou","gb2312","w"}, new string[]{"3721","gb2312","p"},
new string[]{"openfind","utf8","q"}, new string[]{"alltheweb","utf8","q"},
new string[]{"lycos","utf8","query"}, new string[]{"onseek","utf8","q"}
};
public string SearchKey(string myString)
{
EngineRegEx(myString.ToLower());
if (_EngineName != "")
{
Regex myReg = new Regex(_Regex, RegexOptions.IgnoreCase);
Match matche = myReg.Match(myString);
myString = matche.Groups["key"].Value.Replace("+", " ");
if (_Coding == "gb2312")
myString = GetUTF8String(myString);
else
myString = Uri.UnescapeDataString(myString);
}
return myString;
}
private string GetUTF8String(string myString)
{
Regex myReg = new Regex("(?<key>%..%..)", RegexOptions.IgnoreCase);
foreach (Match m in myReg.Matches(myString))
myString = myString.Replace(m.Value, GB2312ToUTF8(m.Value));
return myString;
}
private string GB2312ToUTF8(string myString)
{
string[] parts = myString.Split('%');
byte[] gbBytes = new byte[] { Convert.ToByte(parts[1], 16), Convert.ToByte(parts[2], 16) };
byte[] utf8Bytes = Encoding.Convert(Encoding.GetEncoding("GB2312"), Encoding.UTF8, gbBytes);
char[] chars = new char[Encoding.UTF8.GetCharCount(utf8Bytes)];
Encoding.UTF8.GetChars(utf8Bytes, 0, utf8Bytes.Length, chars, 0);
return new string(chars);
}
// 另有 isCrawler 方法識別搜尋引擎爬蟲
}
Encoding.Convert 高效轉碼。%XX%XX),避免誤傷單位元組字元。