UFO ET IT

WebClient.DownloadString()이 고유 문자가 포함된 문자열을 반환합니다.

ufoet 2023. 6. 22. 23:13
반응형

WebClient.DownloadString()이 고유 문자가 포함된 문자열을 반환합니다.

제가 만들고 있는 화면 스크래핑 도구를 위해 웹에서 다운로드하는 몇 가지 콘텐츠에 문제가 있습니다.

아래 코드에서 웹 클라이언트 다운로드 문자열 메서드에서 반환된 문자열은 일부 웹 사이트에 대해 소스 다운로드에 대한 일부 홀수 문자를 반환합니다.

최근에 아래와 같이 http 헤더를 추가하였습니다.이전에는 헤더 없이 동일한 코드를 호출했습니다.나는 '문자 집합 수락' 헤더에 대한 변형을 시도해 본 적이 없고, 텍스트 인코딩에 대해서는 기본적인 것 외에는 잘 모릅니다.

제가 언급하는 문자 또는 문자 시퀀스는 다음과 같습니다.

¿»""

그리고.

""

웹 브라우저에서 "view source"를 사용할 때는 이러한 문자가 표시되지 않습니다.이 문제의 원인은 무엇이며 문제를 해결하려면 어떻게 해야 합니까?

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

windows-1252는 옥텟을 나타냅니다.EF BB BF이것은 UTF-8 바이트 순서 마커입니다. 즉, 원격 웹 페이지가 UTF-8로 인코딩되어 있지만 Windows-1252인 것처럼 읽습니다.서류에 따르면,WebClient.DownloadString원격 리소스를 문자열로 변환할 때 인코딩으로 사용합니다.으로 설정System.Text.Encoding.UTF8그리고 이론적으로 작동해야 합니다.

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

...그리고 이것이 마지막입니다.

var client = new WebClient { Encoding = System.Text.Encoding.UTF8 };

var json = client.DownloadString(url);

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

나의 경우, 나는 언어, 문자셋 등과 관련된 헤더를 삭제했습니다. 사용자 에이전트와 쿠키를 제외하고는 작동했습니다.

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

언급URL : https://stackoverflow.com/questions/4716470/webclient-downloadstring-returns-string-with-peculiar-characters

반응형