คำถาม:
เมื่อเครื่องมือรวบรวมข้อมูลเว็บรวบรวมข้อมูลหน้าเว็บโดยอัตโนมัติ บางหน้าดูเหมือนจะอ่านไม่ออก สาเหตุคือ:
ใช้ประเภทการเข้ารหัสที่ไม่ถูกต้องในการอ่านข้อมูลเพจ ข้อมูลการเข้ารหัสที่ C#.NET ได้รับจากคลาสปัจจุบันบางครั้งก็ผิด ฉันคิดว่าสำหรับแอปพลิเคชันที่ไม่ใช่ ASP.NET ข้อมูลการเข้ารหัสที่อ่านนั้นผิด
แก้ปัญหา:
แนวคิด: ก่อนอื่นคุณต้องได้รับการเข้ารหัสของเพจขณะรันไทม์ จากนั้นจึงอ่านเนื้อหาของเพจ เพื่อไม่ให้เนื้อหาของเพจที่ได้รับอ่านไม่ออก
วิธี:
1: ใช้การเข้ารหัส ASCII เพื่ออ่านเนื้อหาของหน้า
2: ใช้นิพจน์ทั่วไปเพื่อกรองข้อมูลการเข้ารหัสของเพจออกจากเนื้อหาหน้าที่อ่าน ข้อมูลเพจที่ได้รับในขั้นตอนก่อนหน้าอาจอ่านไม่ออก แต่มาร์กอัป HTML นั้นถูกต้อง และข้อมูลทั้งหมดที่เข้ารหัสสามารถรับได้จากมาร์กอัป HTML
3. ใช้ประเภทการเข้ารหัสที่ถูกต้องเพื่ออ่านข้อมูลหน้า
หากใครมีวิธีการที่ดีกว่านี้โปรดให้ความกระจ่างแก่ฉันด้วย!
รหัสที่แนบมาด้านล่าง:
การสาธิตรหัส
ใช้ระบบ;
ใช้ System.Collections.Generic;
ใช้ System.Text;
ใช้ System.Net;
ใช้ System.Web;
ใช้ System.IO;
ใช้ System.Text.RegularExpressions;
เนมสเปซชุดอักขระ
-
โปรแกรมชั้นเรียน
-
โมฆะคงที่หลัก (สตริง [] args)
-
สตริง url = " http://www.gdqy.edu.cn ";
GetCharset1(url);
GetChartset2(url);
Console.Read();
-
// รับการเข้ารหัสหน้าโดยตรงผ่าน HttpWebResponse
โมฆะคงที่ GetCharset1 (URL สตริง)
-
พยายาม
-
WebRequest webRequest = WebRequest.Create (url);
HttpWebResponse webResponse = (HttpWebResponse) webRequest.GetResponse();
ชุดอักขระสตริง = webResponse.CharacterSet;
สตริง contentEncoding = webResponse.ContentEncoding;
string contentType = webResponse.ContentType;
Console.WriteLine("context type:{0}", contentType);
Console.WriteLine("charset:{0}", charset);
Console.WriteLine("เนื้อหาการเข้ารหัส:{0}" , การเข้ารหัสเนื้อหา);
//ทดสอบหรือดึงข้อมูลว่าหน้าอ่านไม่ออกหรือไม่
//Console.WriteLine(getHTML(url,charset));
-
จับ (เช่น UriFormatException)
{
Console.WriteLine (เช่นข้อความ);
-
จับ (WebException เช่น)
-
Console.WriteLine (เช่น ข้อความ);
-
-
//ใช้นิพจน์ทั่วไปเพื่อรับการเข้ารหัสหน้า
โมฆะคงที่ GetChartset2 (URL สตริง)
{
พยายาม
-
สตริง html = getHTML(url,Encoding.ASCII.EncodingName);
Regex reg_charset = Regex ใหม่(@"charsetbs*=s*(?<charset>[^""]*)");
การเข้ารหัสสตริง = null;
ถ้า (reg_charset.IsMatch(html))
-
การเข้ารหัส = reg_charset.Match(html).Groups["charset"].Value;
Console.WriteLine("ชุดอักขระ:{0}",การเข้ารหัส);
-
อื่น
-
การเข้ารหัส = Encoding.Default.EncodingName;
-
//ทดสอบหรือดึงข้อมูลว่าหน้าอ่านไม่ออกหรือไม่
//Console.WriteLine(getHTML(url,การเข้ารหัส));
-
จับ (เช่น UriFormatException)
{
Console.WriteLine (เช่นข้อความ);
-
จับ (WebException เช่น)
-
Console.WriteLine (เช่น ข้อความ);
-
-
//อ่านวิธีเนื้อหาหน้า
สตริงคงที่ getHTML (URL สตริง, การเข้ารหัสสตริงชื่อ)
{
พยายาม
-
WebRequest webRequest = WebRequest.Create (url);
WebResponse webResponse = webRequest.GetResponse();
สตรีมสตรีม = webResponse.GetResponseStream();
StreamReader sr = StreamReader ใหม่ (สตรีม, Encoding.GetEncoding (encodingName));
สตริง html = sr.ReadToEnd();
ส่งคืน HTML;
-
จับ (เช่น UriFormatException)
{
Console.WriteLine (เช่นข้อความ);
กลับเป็นโมฆะ;
-
catch (เช่น WebException)
{
Console.WriteLine (เช่นข้อความ);
กลับเป็นโมฆะ;
-
-
-
}
รูปแบบการเข้ารหัสที่ใช้ในหน้า http://www.gdqy.edu.cn คือ: gb2312
เนื้อหาที่แสดงโดยวิธีแรกคือ:
ประเภทบริบท:ข้อความ/html
ชุดอักขระ: ISO-8859-1
การเข้ารหัสเนื้อหา:
เนื้อหาที่แสดงโดยวิธีที่สองคือ:
charset:gb2312
ดังนั้นข้อมูลที่ได้รับจากวิธีแรกจึงผิด และวิธีที่สองถูกต้อง
เหตุใดรูปแบบการเข้ารหัสจึงได้รับโดยวิธีแรก: ISO-8859-1
ฉันใช้เครื่องมือ Reflector Reflector เพื่อรับซอร์สโค้ดของคุณสมบัติ CharacterSet และไม่ยากที่จะดูเหตุผล หากเราสามารถรับซอร์สโค้ดของแอตทริบิวต์ ContentType เราก็จะสามารถเห็นสาเหตุของข้อผิดพลาดได้ แต่ฉันไม่สามารถค้นหามันได้หลังจากผ่านไปนานแล้ว หากมีใครสามารถชดเชยมันได้ ฉันก็จะทำ จะขอบคุณมาก
ด้านล่างนี้ฉันแนบเครื่องมือ Reflector เพื่อรับซอร์สโค้ดของคุณสมบัติ CharacterSet เพื่อนๆ ที่สนใจสามารถดูได้
ซอร์สโค้ดชุดอักขระ
CharacterSet สตริงสาธารณะ
-
รับ
-
นี้.CheckDisposed();
สตริง text1 = this.m_HttpResponseHeaders.ContentType;
ถ้า ((this.m_CharacterSet == null) && !ValidationHelper.IsBlankString(text1))
-
this.m_CharacterSet = string.Empty;
สตริง text2 = text1.ToLower (CultureInfo.InvariantCulture);
ถ้า (text2.Trim().StartsWith("ข้อความ/"))
-
this.m_CharacterSet = "ISO-8859-1";
-
int num1 = text2.IndexOf(";");
ถ้า (num1 > 0)
-
ในขณะที่ ((num1 = text2.IndexOf("charset", num1)) >= 0)
-
หมายเลข 1 += 7;
ถ้า ((text2[num1 - 8] == ';') || (text2[num1 - 8] == ' '))
-
ในขณะที่ ((num1 < text2.Length) && (text2[num1] == ' '))
-
หมายเลข 1++;
-
ถ้า ((num1 < (text2.Length - 1)) && (text2[num1] == '='))
-
หมายเลข 1++;
int num2 = text2.IndexOf(';', num1);
ถ้า (num2 > num1)
-
this.m_CharacterSet = text1.Substring(num1, num2).Trim();
หยุดพัก;
-
this.m_CharacterSet = text1.Substring(num1).Trim();
หยุดพัก;
-
-
-
-
-
กลับ this.m_CharacterSet;
}
http://www.cnblogs.com/xuanfeng/archive/2007/01/21/626296.html