Invoke-WebRequest Invoke-RestMethod 乱码研究
powershell Invoke-WebRequest Invoke-RestMethod 乱码 encoding sharset CharacterSet
Invoke-WebRequest和Invoke-RestMethod 爬部分网址会乱码。这个问题很久了,很多人知道。
似乎从有这两个命令的时候起,就有这个问题,至今已经4年有余了,但没人知道原因。或许是没人关注它。
其实这个问题并不难,经我研究,找出了原因,指出了解决方案。
但我当时片面地认为,这有可能和linux的http服务器有关,但后来发现,
http://www.msn.com 是iis网站,微软官方网址,这个网址也有此乱码现象,
最后才确定了这是Invoke-WebRequest Invoke-RestMethod,这两个命令的bug。
才敢给微软提交bug,这个乱码最终的消除,还是要靠微软。
powershell 传教士 原创文章 2016-05-01 允许转载,但必须保留名字和出处,否则追究法律责任
2017-02-10更新: 参见下面的bug报告,由于我报告bug时,只给出了utf8的例子,现在ps5.1版中,发现utf8的bug已经修复了,但gb2312的还没修复。
------------【第一章 编码知识点】-----------------
编码类型,和编码值,是不可分割的一对。所有乱码的产生,是由于只知道编码值,而不知道编码类型! 如:
编码值【70 00 73 00 20 4F 59 65 EB 58】 和 编码类型【utf16】 结合起来,才知道,上述内容是【ps传教士】。
这也是微软发明,在文本中使用【bom头】的原因。
【bom头】【bom头】,有头无乱码!
【bom头】【bom头】,用的人多的牛x文本编辑器,都支持【bom头】,如vi,gedit等。
我以前遇到的某些烂人,怪人。他们很讨厌,微软使用的文本【bom头】,非要不用。非要用某些野路子的奇技淫巧猜测编码。 那么将导致:
1)必然有一定的猜错几率。此乃故意给自己乱码吃。
2)某些文档,如html,可能是多种编码组合的。或许在【<>】中就使用了单独的charset编码。在这种单文件多编码情况下,猜错几率更多。
3)不用【bom头】的.py文档,必然要用 coding:之类的。它们是同一种东西,都是编码类型的标识。
有能耐你别用【bom头】,也别用【coding】,纯猜!脚本编码未知,解析中文注释报错,导致的运行不了 活该! 宁可py脚本不能运行,也别用【bom头】和【coding】
【bom头】只解决了,纯文本文件的乱码。传输字符串的时候,也必须跟着编码类型。一旦编码类型丢失或未知,将产生乱码。
--------------------【第二章 序】--------------------
(PowerShell中的)两只爬虫,两只爬虫,跑地快,爬网页不赖~~~
一只基于com版的ie,一只基于.net中的WebRequest类,都是老奶奶,不奇怪 。。。
虽然很老了,但爬的也很快 。。。
如果你的系统是win8,或者win8以上,或者win7安装了powershell 4.0,5.0,那么 powershell中自带了这样的两个命令,【Invoke-WebRequest】和【Invoke-RestMethod】。 第一个命令返回的是对象,第二个返回的是(整个网页)字符串。
这两个命令有时候会返回乱码,很长一段时间,我认为,是这个命令有解码bug,但后来发现,把结果用其自带的-outfile参数输出到文件之后,编码是正确的。 也就是说,其实是我们不知道怎么解码。只能用写入磁盘的慢方法。
后来我看了博客园友【昵称:老马说编程】的这两篇帖子,琢磨出来的,感谢他! 也请大家先看看这两篇乱码修复类文章。
http://www.cnblogs.com/swiftma/p/5420145.html
http://www.cnblogs.com/swiftma/p/5430007.html
------------【第三章 正文】-----------------
乱码命令版本:
所有版本的powershell。
乱码原因:大概90%以上都是这种问题。
网页编码为utf8,但是接收到编码后,把网页源码,编码类型认错误了,或者说丢失了。 把utf8编码网页源码,错误地认为是iso8859-1编码类型的编码,把此utf8再次转换成了utf8,然后给我们呈现了。
bug重现powershell命令:
Invoke-WebRequest -Uri 'http://www.msn.com' # return chinese messy code (Invoke-WebRequest -Uri 'http://www.msn.com').BaseResponse.CharacterSet # utf8 web page,but return ISO-8859-1 Invoke-RestMethod -Uri 'http://www.msn.com'
修复办法: 对上述编码进行逆转换。
bug修复powershell命令:
$utf8 = [System.Text.Encoding]::GetEncoding(65001) $iso88591 = [System.Text.Encoding]::GetEncoding(28591) #ISO 8859-1 ,Latin-1$wrong_string = Invoke-RestMethod -Uri 'http://www.msn.com' $wrong_bytes = $utf8.GetBytes($wrong_string)$right_bytes = [System.Text.Encoding]::Convert($utf8,$iso88591,$wrong_bytes) #仔细看这里 $right_string = $utf8.GetString($right_bytes) #仔细看这里 write-host $right_string
gbk乱码的解决:网页源码声明了gb2312,浏览器打开正常,但powershell识别不正常的解决。
$gbk = [System.Text.Encoding]::GetEncoding(936) $utf8 = [System.Text.Encoding]::GetEncoding(65001) $iso88591 = [System.Text.Encoding]::GetEncoding(28591) #ISO 8859-1 ,Latin-1$wrong_string = Invoke-RestMethod -Uri 'http://1212.ip138.com/ic.asp' $wrong_bytes = $utf8.GetBytes($wrong_string)$right_bytes = [System.Text.Encoding]::Convert($utf8,$iso88591,$wrong_bytes) #仔细看这里 $right_string = $gbk.GetString($right_bytes) #仔细看这里 write-host $right_string
欢迎去顶这个bug:
https://windowsserver.uservoice.com/forums/301869-powershell/suggestions/13685217-invoke-restmethod-and-invoke-webrequest-encoding-b
问:在这个bug没修复之前,如何用powershell爬数据?
答:请看我这篇文章: 转帖不会乱码的,powershell网络蜘蛛 http://www.cnblogs.com/piapia/p/5093201.html
------------【第四章 后记:分析 列举 网页常用编码类型】-----------------
wincodepage 名称
936 gbk
54936 gb18030
GB18030使用变长编码,有的字符是两个字节,有的是四个字节。 在两字节编码中,字节表示范围与GBK一样。在四字节编码中,第一个字节的值从0x81到0xFE,第二个字节的值从0x30到0x39,第三个字节的值从0x81到0xFE,第四个字节的值从0x30到0x39。 解析二进制时,如何知道是两个字节还是四个字节表示一个字符呢?看第二个字节的范围,如果是0x30到0x39就是四个字节表示,因为两个字节编码中第二字节都比这个大。
932 japanese
949 korean
950 big5
20127 us-ascii us 7bit
1252 ISO-8859-1
28591 ISO 8859-1 又称Latin-1
1200 utf-16
1201 utf-16 Big-Endian
12000 utf-32
12001 utf-32 Big-Endian
65001 utf-8
gb2312,gbk,gb18030,之间是兼容的。由于网页中都是简单中文,所以可以把它们看作是同一种编码。 所以常用(网页!)编码只有,gbk,big5,utf8,ISO 8859-1,1252, 所以常用(文本!)编码只有,gbk,big5,utf8,ISO 8859-1,1252,utf16le,
摘自: https://msdn.microsoft.com/zh-cn/library/system.text.encodinginfo.codepage.aspx
------------【第五章 相关问题】-----------------
问:如何获取网页编码?
答: 下载网页,并查找网页中的charset关键字。
powershell代码: $网址 = 'http://www.baidu.com' $网页编码字串 = (Invoke-RestMethod -Uri $网址 ) -split '>' | select-string "Content-Type.*charset" #如这个百度网页,有些网页没有 "`n" 换行符
问:【Invoke-WebRequest】和【Invoke-RestMethod】如何获取网页编码?
答:
这个获取方法是不可靠的,有些是错误的。powershell传教士注
(Invoke-WebRequest -Uri www.baidu.com ).BaseResponse.CharacterSet #返回 utf-8 (Invoke-WebRequest -Uri news.qq.com ).BaseResponse.CharacterSet #返回 GB2312 (Invoke-WebRequest -Uri http://www.nmc.cn ).Headers.'content-type' #text/html (Invoke-WebRequest -Uri http://www.nmc.cn ).BaseResponse.CharacterSet #ISO-8859-1 (Invoke-WebRequest -Uri http://www.scielo.br).BaseResponse.CharacterSet
问:如何给网页传值?
答:
$text = '要发送的内容' $postData = [System.Text.Encoding]::UTF8.GetBytes($text) Invoke-WebRequest -Uri 'http://www.mydomain.com/' -Method Post -Body $postData -ContentType "text/plain; charset=utf-8"
转载于:https://www.cnblogs.com/piapia/p/5452448.html
Invoke-WebRequest Invoke-RestMethod 乱码研究相关推荐
- method.invoke()和invoke()简单理解
首先说下作用,method.invoke(Object obj,Object args[])的作用就是调用method类代表的方法,其中obj是对象名,args是传入method方法的参数 举个例子: ...
- php有没有invoke,php invoke方法有什么用
php invoke方法是PHP5.3新增的一个魔术方法,该方法可以在创建实例后,直接调用对象,也就是通过函数的方式来使用对象,并且invoke方法也可以带参数. PHP5.3新增了一个叫做__inv ...
- 千万别在UI线程上调用Control.Invoke和Control.BeginInvoke,因为这些是依然阻塞UI线程的,造成界面的假死...
.c# Invoke和BeginInvoke 区别 Control.Invoke 方法 (Delegate):在拥有此控件的基础窗口句柄的线程上执行指定的委托. Control.BeginInvoke ...
- 委托的Invoke 和 BeginInvoke 与Control的Invoke和BeginInvoke(转-因为写得很好)
原文地址:http://www.cnblogs.com/worldreason/archive/2008/06/09/1216127.html Invoke and BeginInvoke Invok ...
- c# Invoke和BeginInvoke 区别
转自http://www.cnblogs.com/c2303191/articles/826571.html Control.Invoke 方法 (Delegate) :在拥有此控件的基础窗口句柄的线 ...
- c# Invoke和BeginInvoke 区别详解
Control.Invoke 方法 (Delegate):在拥有此控件的基础窗口句柄的线程上执行指定的委托. Control.BeginInvoke 方法 (Delegate) :在创建控件的基础句柄 ...
- C#中Invoke 和 BeginInvoke的涵义和区别
BeginInvoke 方法真的是新开一个线程进行异步调用吗? 参考以下代码: public delegate void treeinvoke(); private void UpdateTreeVi ...
- c# Invoke和BeginInvoke
*************************************************** 更多精彩,欢迎进入:http://shop115376623.taobao.com ****** ...
- C#中Invoke 和 BeginInvoke 的区别
Invoke 和 BeginInvoke 的真正涵义 .在多线程中如何调用Winform Control.Invoke 方法 (Delegate) :在拥有此控件的基础窗口句柄的线程上执行指定的委托. ...
- Invoke and BeginInvoke BeginInvoke和EndInvoke方法 (转)3
近日,被Control的Invoke和BeginInvoke搞的头大,就查了些相关的资料,整理如下.感谢这篇文章对我的理解Invoke和BeginInvoke的真正含义 . (一)Control的In ...
最新文章
- linux配置adb环境变量配置,Ubuntu下adb环境配置
- 蓝桥分酒java_[蓝桥杯][java]海盗分酒
- asp.net 连接字符串的多种写法
- linux系统服务详解 用于Linux系统服务优化
- kubernetes1.8.4 安装指南 -- 8. 安装Kube DNS
- java log4j logback jcl_内部分享:如何解决Java日志框架冲突问题。
- 网络游戏的客户端同步问题 .
- 图解数字签名Digital Signature 和数字证书Public-key certificate
- BeanFactory容器的设计原理
- 使用PO+跨平台改造Macaca示例(APP端)
- php-5.6.31安装视频教程_php安装图解教程
- 数据集如何影响作物病害识别的有效性
- 重拾Javascript(五)--优化字符串操作
- 亮剑:PHP,我的未来不是梦(6)
- RSA 加解密 1024 位 2048 位
- 【EJB基础】开发一个简单的EJB应用程序
- “配置系统未能初始化” 异常解决
- android 文件保存到应用和sd卡中
- Pandas常用函数大合集
- 微信分享网页 图标不显示
热门文章
- 区块链 数据读权限 设计方案
- 软件工程 CI持续集成实例 Zanata+github+Jenkins
- thinkphp 捕捉错误
- mysql获取上周时间戳_php、mysql查询当天,查询本周,查询本月的数据实例(字段是时间戳)...
- JavaSE——Java8之Stream流
- 多线程测试时的辅助类--CountDownLatch
- linux中config文件怎么打开,linux-如何使用CoreOS的cloud-config文件启动Dock...
- hwd分别是长宽高_丰田重磅新RAV4荣放!不仅颜值高了 配置还再升级,仅18万
- mbr linux安装分区,linux – 在MBR扇区上安装GRUB或在启动分区上安装第一个扇区之间的区别?...
- LayaAir 对象池 laya.utils.Pool