首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >来自WebClient html的汉字与网站上的实际汉字不同

来自WebClient html的汉字与网站上的实际汉字不同
EN

Stack Overflow用户
提问于 2018-04-15 20:20:11
回答 1查看 466关注 0票数 2

因此,我试图从一个名为Kanji-A-Day.com的网站获得一部分文本,但我有一个问题。

你看,我正试着从网站上得到每日的汉字,我能够把HTML缩小到我想要的范围,但似乎字符是不同的。

这看起来像什么

看起来像

更奇怪的是,我直接从网站复制和粘贴第二张图片,所以这不是字体问题。

下面是我用来获取字符的代码:

代码语言:javascript
复制
public void UpdateDailyKanji() // Called at the initialization of a new main form
{
    string kanji;
    using (WebClient client = new WebClient()) // Grab the string 
        kanji = client.DownloadString("http://www.kanji-a-day.com/level4/index.php"); 
    // Trim the HTML to just the Kanji
    kanji = kanji.Remove(0, kanji.IndexOf(@"<div class=""glyph"">") + 19);
    kanji = kanji.Remove(kanji.IndexOf("</div>")-2);
    kanji = kanji.Trim();
    Text_DailyKanji.Text = kanji; // Set the Kanji
}

有人知道这是怎么回事吗?我猜是因为Unicode的原因,但我对此不太了解。

提前谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-04-16 00:22:41

您试图以字符串形式下载的页面使用charset=EUC-JP (也称为Japanese (EUC) (CodePage 51932) )进行编码。这显然是在页面标题中设置的。

为什么WebClient.DownloadString返回的字符串使用错误的编码器编码?

MSDN文档声明如下:

此方法检索指定的资源。下载资源后,该方法将使用“编码”属性中指定的编码将资源转换为字符串。

因此,您必须事先知道将使用什么编码,并指定它,并设置WebClient.Encoding属性。

要验证这一点,请检查用于.NET的WebClient.DownloadString参考源方法:

代码语言:javascript
复制
try {
    WebRequest request;
    byte [] data = DownloadDataInternal(address, out request);
    string stringData = GetStringUsingEncoding(request, data);
    if(Logging.On)Logging.Exit(Logging.Web, this, "DownloadString", stringData);
    return stringData;
    } finally {
        CompleteWebClientState();
    }

编码是使用请求设置设置的,而不是响应设置。

结果是,下载的字符串使用默认的CodePage进行编码。

你现在能做的是:

  • 下载该页面两次,第一次检查WebClient编码和Html编码是否不匹配。
  • 用正确的编码重新编码字符串,设置在基础WebResponse中.
  • 不要使用WebClient,直接使用HttpClient或WebRequest。或者,如果您喜欢这个工具,可以创建一个定制的WebClient类来更直接地处理WebRequest/WebResponse。

这是一种执行重新编码任务的方法:

WebClient返回的字符串被转换为字节数组并传递给MemoryStream,然后使用从Content-Type: charset响应头检索到的编码的StreamReader重新编码。

编辑:

现在使用Reflection从底层HttpWebResponse获取页面Encoding。这将避免解析由远程响应定义的原始CharacterSet时的错误。

代码语言:javascript
复制
using System.IO;
using System.Net;
using System.Reflection;
using System.Text;

public string WebClient_DownLoadString(Uri uri)
{
    using (var client = new WebClient())
    {
        // If Windows 7 - Windows Server 2008 R2
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

        client.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.BypassCache);
        client.Headers.Add(HttpRequestHeader.Accept, "ext/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
        client.Headers.Add(HttpRequestHeader.AcceptLanguage, "en-US,en;q=0.8");
        client.Headers.Add(HttpRequestHeader.KeepAlive, "keep-alive");

        string result = client.DownloadString(uri);

        var flags = BindingFlags.Instance | BindingFlags.NonPublic;
        using (var response = (HttpWebResponse)client.GetType().GetField("m_WebResponse", flags).GetValue(client))
        {
            var pageEncoding = Encoding.GetEncoding(wc_response.CharacterSet);
            byte[] bytes = client.Encoding.GetBytes(result);
            using (var ms = new MemoryStream(bytes, 0, bytes.Length))
            using (var reader = new StreamReader(ms, pageEncoding))
            {
                ms.Position = 0;
                return reader.ReadToEnd();
            };
        };
    }
}

现在,您的代码应该以正确的形式获得日语字符。

代码语言:javascript
复制
Uri uri = new Uri("http://www.kanji-a-day.com/level4/index.php", UriKind.Absolute);
string kanji = WebClient_DownLoadString(uri);

kanji = kanji.Remove(0, kanji.IndexOf("<div class=\"glyph\">") + 19);
kanji = kanji.Remove(kanji.IndexOf("</div>")-2);
kanji = kanji.Trim();

Text_DailyKanji.Text = kanji;
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49846392

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档