ProgramingTip

WebClient.DownloadString ()은 고유 한 문자가있는 곳을 반환합니다.

bestdevel 2020. 11. 26. 19:41
반응형

WebClient.DownloadString ()은 고유 한 문자가있는 곳을 반환합니다.


내가 만든 화면 스크래핑 도구를 위해 웹에서 다운로드하는 일부 콘텐츠에 문제가 있습니다.

아래 코드에서 웹 클라이언트 다운로드 절차에서 반환 된 코드는 일부 (전체가 아님) 웹 사이트에 대한 소스 다운로드에 대해 일부 이상한 문자를 반환합니다.

최근에 다음에 같이 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);

옥텟의 windows-1252 표현입니다 EF BB BF. UTF-8 바이트 순서 마커입니다 . 이는 마치 원격 웹 페이지가 UTF-8로 인코딩 마치 windows-1252 인 것처럼 읽고 있음을 의미합니다. 워드 프로세서에 따르면 , WebClient.DownloadString사용 이 고도로 원격 리소스를 변환 할 때의 코딩한다. 로 설정하면 이론적으로 작동해야합니다.Webclient.EncodingSystem.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);

제 경우에는 사용자 에이전트와 쿠키를 제외하고 언어, 문자셋 수신 헤더를 삭제했습니다. 효과가 ..

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

그들 중 어느 것도 "www.yahoo.com"과 같은 몇몇 특별한 웹 사이트에서 저를 위해 작동하지 않았습니다. 나는 내 문제를 해결하는 유일한 방법은 변화되었다 DownloadStringOpenRead와 사용 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();

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

반응형