c# - إرجاع WebClient.DownloadString() سلسلة أحرف الأحرف الغريبة



asp.net .net (4)

لدي مشكلة في بعض المحتوى الذي نقوم بتنزيله من الويب لأداة كشط الشاشة التي أقوم بإنشائها.

في التعليمة البرمجية أدناه ، ترجع السلسلة التي تم إرجاعها من طريقة سلسلة تنزيل عميل ويب بعض الأحرف الفردية للتنزيل المصدر لبعض مواقع الويب (وليس كلها).

لقد أضفت عناوين http في الآونة الأخيرة على النحو التالي. في السابق كان يتم استدعاء نفس الرمز بدون الرؤوس لنفس التأثير. لم أحاول إدخال تنويعات على رأس "Accept-Charset" ، لا أعرف الكثير عن ترميز النص بخلاف الأساسيات.

الشخصيات ، أو تسلسل الأحرف التي أشرت إليها هي:

" ï» ¿ "

و

" Â "

لا يتم مشاهدة هذه الأحرف عند استخدام "عرض المصدر" في متصفح الويب. ما الذي يمكن أن يسبب هذا وكيف يمكنني تصحيح المشكلة؟

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);

https://src-bin.com


Answer #1

طريقة تنفيذ 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);

...وهذا كل شيء.


Answer #2

في حالتي ، أنا حذف رأس من أي وقت مضى المتعلقة باللغة ، charset إلخ وكيل المستخدم وكيل وملف تعريف الارتباط. انها عملت..

 // 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");

Answer #3

لم يعمل أي منهم بالنسبة لي لبعض المواقع الخاصة مثل "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();

Answer #4

 هو تمثيل windows-1252 من الثمانيات EF BB BF . هذا هو علامة UTF-8 byte-order ، والتي تعني أن صفحتك على الويب البعيد يتم ترميزها في UTF-8 ولكنك تقرأها كما لو كانت windows-1252. طبقًا للمستندات ، يستخدم WebClient.DownloadString Webclient.Encoding له عندما يحول المورد البعيد إلى سلسلة. System.Text.Encoding.UTF8 إلى System.Text.Encoding.UTF8 ويجب أن تعمل الأشياء من الناحية النظرية.





special-characters