Итак, я пытаюсь получить часть текста с сайта Kanji-A-Day.com , но у меня есть проблема.
Понимаете, я пытаюсь получить ежедневный кандзи с веб-сайта, и я смог сузить HTML до того, что хочу, но, похоже, у персонажей разные …?
На что это похоже
Как это должно выглядеть
Что еще более странно, так это то, что я произвел результаты для второго изображения путем копирования и вставки непосредственно с сайта, так что это не проблема шрифта.
Вот код, который я использую для получения символа:
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(@"") + 19); kanji = kanji.Remove(kanji.IndexOf("")-2); kanji = kanji.Trim(); Text_DailyKanji.Text = kanji; // Set the Kanji }
Кто-нибудь знает, что здесь происходит? Я предполагаю, что это какая-то вещь в Юникоде, но я мало что знаю об этом.
Заранее спасибо.
Страница, которую вы пытаетесь загрузить в виде строки, кодируется с использованием charset=EUC-JP
, также известного как Japanese (EUC)
(CodePage 51932). Это явно указано в заголовках страниц.
Почему строка, возвращаемая WebClient.DownloadString, закодирована с использованием неправильного кодировщика?
В документах MSDN указано следующее:
Этот метод извлекает указанный ресурс. После загрузки ресурса метод использует кодировку, указанную в свойстве Encoding, для преобразования ресурса в String.
Таким образом, вы должны заранее знать, какая кодировка будет использоваться и указать ее, задав свойство WebClient.Encoding .
Чтобы убедиться в этом, проверьте исходный источник .NET для метода WebClient.DownloadString :
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-страницы.
– Перекодируйте строку с правильной кодировкой.
Это метод выполнения последней задачи:
Строка, возвращаемая WebClient, преобразуется в массив байтов и передается в MemoryStream
, а затем повторно кодируется с помощью StreamReader
с StreamReader
полученным из заголовка ответа заголовка Content-Type: charset
.
РЕДАКТИРОВАТЬ:
Теперь с помощью Reflection
получите страницу Encoding
из базового HttpWebResponse
. Это должно избегать ошибок при анализе исходного CharacterSet
как определено удаленным ответом.
using System.IO; using System.Net; using System.Reflection; using System.Text; public string WebClient_DownLoadString(Uri URI) { using (WebClient webclient = new WebClient()) { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; webclient.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.BypassCache); webclient.Headers.Add(HttpRequestHeader.Accept, "ext/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); webclient.Headers.Add(HttpRequestHeader.AcceptLanguage, "en-US,en;q=0.8"); webclient.Headers.Add(HttpRequestHeader.KeepAlive, "keep-alive"); string result = webclient.DownloadString(URI); using (HttpWebResponse wc_response = (HttpWebResponse)webclient .GetType() .GetField("m_WebResponse", BindingFlags.Instance | BindingFlags.NonPublic) .GetValue(webclient)) { Encoding PageEncoding = Encoding.GetEncoding(wc_response.CharacterSet); byte[] bresult = webclient.Encoding.GetBytes(result); using (MemoryStream memstream = new MemoryStream(bresult, 0, bresult.Length)) using (StreamReader reader = new StreamReader(memstream, PageEncoding)) { memstream.Position = 0; return reader.ReadToEnd(); }; }; } }
Теперь ваш код должен получить японские символы в их правильной форме.
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(@"") + 19); kanji = kanji.Remove(kanji.IndexOf("")-2); kanji = kanji.Trim(); Text_DailyKanji.Text = kanji; // Set the Kanji