WebClient. DownloadString () возвращает строку со специфическими символами

У меня есть проблема с некоторым содержанием, которое мы загружаем с сети для инструмента анализа экранных данных, который я создаю.

в коде ниже, строка, возвращенная из строкового метода загрузки веб-клиента, возвращает некоторые нечетные символы для исходной загрузки для некоторых (не все) веб-сайты.

Я недавно добавил http заголовки как ниже. Ранее тот же код назвали без заголовков к тому же эффекту. Я не попробовал вариации на заголовок 'Принимать-набора-символов', я не знаю много о текстовом кодировании кроме основ.

Символы или последовательности символов, к которым я обращаюсь:

"ï» ¿"

и

"Â"

Эти символы не замечены при использовании "источника представления" в веб-браузере. Что могло вызывать это и как я могу исправить проблему?

string urlData = String.Empty;
WebClient wc = new WebClient();

// Add headers to impersonate a web browser. Some web sites 
// will not respond correctly without these headers
wc.Headers.Add("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12");
wc.Headers.Add("Accept", "*/*");
wc.Headers.Add("Accept-Language", "en-gb,en;q=0.5");
wc.Headers.Add("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");

urlData = wc.DownloadString(uri);
62
задан 5 May 2015 в 13:19

5 ответов

 представление 1252 окон октетов EF BB BF. Это маркер порядка байтов UTF-8, который подразумевает, что Ваша удаленная веб-страница кодируется в UTF-8, но Вы читаете его, как будто это были окна 1252. Согласно использованию документов , WebClient.DownloadString Webclient.Encoding как его кодирование, когда это преобразовывает удаленный ресурс в строку. Установите его на System.Text.Encoding.UTF8, и вещи должны теоретически работать.

99
ответ дан 31 October 2019 в 13:27

Путь WebClient.DownloadString реализован, очень немое. Это должно получить кодировку символов от Content-Type заголовок в ответе, но вместо этого это ожидает, что разработчик скажет ожидаемое кодирование заранее. Я не знаю то, что думали разработчики этого класса.

я создал вспомогательный класс, который получает имя кодирования от Content-Type заголовок ответа:

public static class WebUtils
{
    public static Encoding GetEncodingFrom(
        NameValueCollection responseHeaders,
        Encoding defaultEncoding = null)
    {
        if(responseHeaders == null)
            throw new ArgumentNullException("responseHeaders");

        //Note that key lookup is case-insensitive
        var contentType = responseHeaders["Content-Type"];
        if(contentType == null)
            return defaultEncoding;

        var contentTypeParts = contentType.Split(';');
        if(contentTypeParts.Length <= 1)
            return defaultEncoding;

        var charsetPart =
            contentTypeParts.Skip(1).FirstOrDefault(
                p => p.TrimStart().StartsWith("charset", StringComparison.InvariantCultureIgnoreCase));
        if(charsetPart == null)
            return defaultEncoding;

        var charsetPartParts = charsetPart.Split('=');
        if(charsetPartParts.Length != 2)
            return defaultEncoding;

        var charsetName = charsetPartParts[1].Trim();
        if(charsetName == "")
            return defaultEncoding;

        try
        {
            return Encoding.GetEncoding(charsetName);
        }
        catch(ArgumentException ex) 
        {
            throw new UnknownEncodingException(
                charsetName,   
                "The server returned data in an unknown encoding: " + charsetName, 
                ex);
        }
    }
}

(UnknownEncodingException пользовательский класс исключений, не стесняйтесь заменять для InvalidOperationException или безотносительно если Вы захотите)

Затем следующий дополнительный метод для WebClient, то класс добьется цели:

public static class WebClientExtensions
{
    public static string DownloadStringAwareOfEncoding(this WebClient webClient, Uri uri)
    {
        var rawData = webClient.DownloadData(uri);
        var encoding = WebUtils.GetEncodingFrom(webClient.ResponseHeaders, Encoding.UTF8);
        return encoding.GetString(rawData);
    }
}

Так в Вашем примере Вы сделали бы:

urlData = wc.DownloadStringAwareOfEncoding(uri);

... и вот именно.

48
ответ дан 31 October 2019 в 13:27
var client = new WebClient { Encoding = System.Text.Encoding.UTF8 };

var json = client.DownloadString(url);
14
ответ дан 31 October 2019 в 13:27

в моем случае я удалял когда-либо заголовок, связанный с языком, набор символов и т.д. Кроме агента пользователя и cookie. это работало..

 // try commenting
 //wc.Headers.Add("Accept-Language", "en-gb,en;q=0.5");
 //wc.Headers.Add("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
0
ответ дан 31 October 2019 в 13:27

Ни один из них не работал на меня для некоторых специальных веб-сайтов, таких как "www.yahoo.com". Единственный способ, которым я разрешаю свою проблему, изменял DownloadString на OpenRead и использовал UserAgent заголовок как пример кода. Однако несколько сайтов как "www.varzesh3.com" не работали ни с одним из методов!

WebClient client = new WebClient()    
client.Headers.Add(HttpRequestHeader.UserAgent, "");
var stream = client.OpenRead("http://www.yahoo.com");
StreamReader sr = new StreamReader(stream);
s = sr.ReadToEnd();
0
ответ дан 31 October 2019 в 13:27

Другие вопросы по тегам:

Похожие вопросы: