WebClient.DownloadString()返回具有特殊字符的string
我有一个内容,我们正在从网上下载一个屏幕抓取工具,我正在build设的问题。
在下面的代码中,从Web客户端下载string方法返回的string返回一些(不是全部)网站的源下载的一些奇怪的字符。
我最近添加了如下的http头文件。 以前相同的代码被调用,没有标题相同的效果。 我没有试过“Accept-Charset”标题的变体,除了基础知识以外,我对文本编码知之甚less。
我所指的字符或字符序列是:
“ ï¿¿ ”
和
“ Â ”
当您在networking浏览器中使用“查看源代码”时,不会看到这些字符。 什么可能导致这个问题,我该如何纠正这个问题?
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);
是EF BB BF
的八EF BB BF
组的窗口-1252表示。 这是UTF-8字节顺序的标记 ,这意味着你的远程网页是用UTF-8编码的,但是你正在读它,就好像它是windows-1252一样。 根据文档 , WebClient.DownloadString
在将远程资源转换为string时使用Webclient.Encoding
作为其编码。 将其设置为System.Text.Encoding.UTF8
,理论上应该起作用。
WebClient.DownloadString
的实现方式非常愚蠢。 它应该从响应中的Content-Type
头部获得字符编码,但是却期望开发人员事先告诉预期的编码。 我不知道这个class的开发者在想什么。
我创build了一个辅助类,它从响应的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
是一个自定义的exception类,随意replaceInvalidOperationException
或任何其他如果你想要的)
然后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);
在我的情况下,返回的数据是gzipped,必须先解压缩,所以我发现这个答案有帮助:
在我的情况下,我删除了有关语言,字符集等除了用户代理和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");