Curl 采集乱码 gzip 原因及解决方案 utf-8
用curl获取一个经过gzip压缩后的网页时返回乱码
原因大体就是服务器返回的Content-Encoding的值和网页的编码不同,造成curl解码出问题,直接将gzip或deflate编码的文件下载了,所以看起来是乱码了。
Content-Encoding: gzip
读取前几个字节为:1F 8B 08 ,其中1F 8B表明为gzip压缩,而08表示为deflate压缩。
这样实际编码和通过Content-Encoding获取的编码不一样,所以curl解码出错,导致下载的是未解码的页面,也就是一堆乱码。
知道了原因,就有了解决方案了
可以通过读取下载的二进制文件的前3个字节,来判断是否是压缩文件
以下是采集163和sohu(gzip过) 的首页的不同方法
$curl=curl_init('http://www.163.com');
curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
curl_setopt($curl,CURLOPT_USERAGENT,'Mozilla/4.0
(compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322)');
$html=curl_exec($curl);
var_dump($html);
$curl=curl_init('http://www.sohu.com');
curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
curl_setopt($curl,CURLOPT_USERAGENT,'Mozilla/4.0
(compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322)');
$html=curl_exec($curl);
//$html=strstr($html,'<');
$html=gzdecode($html);
var_dump($html);
function gzdecode($data)
{
$len = strlen($data);
if ($len < 18 || strcmp(substr($data,0,2),"\x1f\x8b"))
{
return null; // Not
GZIP format (See RFC 1952)
}
$method = ord(substr($data,2,1)); // Compression
method
$flags = ord(substr($data,3,1)); // Flags
if ($flags & 31 != $flags)
{
// Reserved bits are set -- NOT ALLOWED by RFC 1952
return null;
}
// NOTE: $mtime may be negative (PHP integer limitations)
$mtime = unpack("V", substr($data,4,4));
$mtime = $mtime[1];
$xfl = substr($data,8,1);
$os = substr($data,8,1);
$headerlen = 10;
$extralen = 0;
$extra = "";
if ($flags & 4)
{
// 2-byte length prefixed EXTRA data in header
if ($len - $headerlen - 2 < 8)
{
return false; // Invalid
format
}
$extralen = unpack("v",substr($data,8,2));
$extralen = $extralen[1];
if ($len - $headerlen - 2 - $extralen < 8)
{
return false; // Invalid
format
}
$extra = substr($data,10,$extralen);
$headerlen += 2 + $extralen;
}
$filenamelen = 0;
$filename = "";
if ($flags & 8)
{
// C-style string file NAME data in header
if ($len - $headerlen - 1 < 8)
{
return false; // Invalid
format
}
$filenamelen = strpos(substr($data,8+$extralen),chr(0));
if ($filenamelen === false || $len - $headerlen - $filenamelen - 1 < 8)
{
return false; // Invalid
format
}
$filename = substr($data,$headerlen,$filenamelen);
$headerlen += $filenamelen + 1;
}
$commentlen = 0;
$comment = "";
if ($flags & 16)
{
// C-style string COMMENT data in header
if ($len - $headerlen - 1 < 8)
{
return false; // Invalid
format
}
$commentlen = strpos(substr($data,8+$extralen+$filenamelen),chr(0));
if ($commentlen === false || $len - $headerlen - $commentlen - 1 < 8)
{
return false; // Invalid
header format
}
$comment = substr($data,$headerlen,$commentlen);
$headerlen += $commentlen + 1;
}
$headercrc = "";
if ($flags & 1)
{
// 2-bytes (lowest order) of CRC32 on header present
if ($len - $headerlen - 2 < 8)
{
return false; // Invalid
format
}
$calccrc = crc32(substr($data,0,$headerlen)) & 0xffff;
$headercrc = unpack("v", substr($data,$headerlen,2));
$headercrc = $headercrc[1];
if ($headercrc != $calccrc)
{
return false; // Bad
header CRC
}
$headerlen += 2;
}
// GZIP FOOTER - These be negative due to PHP's limitations
$datacrc = unpack("V",substr($data,-8,4));
$datacrc = $datacrc[1];
$isize = unpack("V",substr($data,-4));
$isize = $isize[1];
// Perform the decompression:
$bodylen = $len-$headerlen-8;
if ($bodylen < 1)
{
// This should never happen - IMPLEMENTATION BUG!
return null;
}
$body = substr($data,$headerlen,$bodylen);
$data = "";
if ($bodylen > 0)
{
switch ($method)
{
case 8:
// Currently the only supported compression method:
$data = gzinflate($body);
break;
default:
// Unknown compression method
return false;
}
} else {
// I'm not sure if zero-byte body content is allowed.
// Allow it for now... Do nothing...
}
// Verifiy decompressed size and CRC32:
// NOTE: This may fail with large data sizes depending on how
// PHP's integer limitations affect strlen() since $isize
// may be negative for large sizes.
if ($isize != strlen($data) || crc32($data) != $datacrc)
{
// Bad format! Length or CRC doesn't match!
return false;
}
return $data;
}
还有文提到:
curl_setopt($this->curl,CURLOPT_ENCODING ,'gzip')
或
zlib库中的gzuncompress函数
shell用curl抓取页面乱码,参考一下2方面:
1.是用curl抓取的数据是用类似gzip压缩后的数据导致的乱码。
乱码:curl www.1ting.com | more
乱码:curl -H "Accept-Encoding: gzip" www.1ting.com | more
不乱码:curl -H "Accept-Encoding: gzip" www.1ting.com | gunzip | more
不乱码:curl www.1616.net | more
乱码:curl -H "Accept-Encoding: gzip" www.1616.net | more
不乱码:curl -H "Accept-Encoding: gzip" www.1616.net | gunzip | more
下面的a,b解释的是www.1ting.com,c,d解释是的www.1616.net
a.某个url,如果用不加任何选项的curl命令抓取后乱码,在curl后面加上Accept-Encoding: gzip,后面不加gunzip,则抓取的数据会乱码。
b.某个url,如果用不加任何选项的curl命令抓取后乱码,在curl后面加上Accept-Encoding: gzip,后面加上gunzip,则抓取的数据不会乱码。
c.某个url,如果用不加任何选项的curl命令抓取后不乱码,在curl后面加上Accept-Encoding: gzip,后面不加gunzip,则抓取的数据会乱码。
d.某个url,如果用不加任何选项的curl命令抓取后不乱码,在curl后面加上Accept-Encoding: gzip,后面加上gunzip,则抓取的数据不会乱码。
小总:
也就是说在curl后面加上Accept-Encoding: gzip,再用gunzip解压缩,则基本上可以保存数据不乱码。
2.GBK或者UTF8汉字之类的乱码
iconv
命令是运行于linux平台的文件编码装换工具。当我们在linux系统shell下通过curl命令或者wget命令获取一个网页的源代码,当网页的编
码与当前操作系统坏境的设置的编码不同时,就会发现网页中有很多乱码。如在网页"meta"标签"charset"属性值设置为"gb2312"的http://www.baidu.com百
度首页,在系统坏境变量"$LANG"值为"en_US.UTF-8"的linux系统即会产生中文乱码现象。这时我们可以尝试使用iconv命令进行编
码装换,让中文不在是乱码。如下命令是处理百度在系统坏境变量"$LANG"值为"en_US.UTF-8"的linux系统乱码的问题的解决方案之一:
curl http://www.baidu.com|iconv
-f gb2312 -t utf-8
当然,你也通过改变系统坏境变量与百度首页的"charset"值一致,也可以解决此乱码问题,如下命令:
set LANG="gb2312"
export LANG
curl http://www.baidu.com
iconv命令的详细语法:
iconv [选项..] [文件..]
选项:
-f 输入编码
-t 输出编码
-l 列出所有已知的编码
-o 输出文件
对比采用PHP CURL库的POST GET HEADER三种方法之间的差异
比较POST
GET HEADER这三种方法的区别:
|
参数 |
POST |
GET |
HEADER |
|
CURLOPT_URL |
有 |
有 |
有 |
|
CURLOPT_POST |
开启 |
关闭 |
关闭 |
|
CURLOPT_HTTPHEADER |
如果有$header,则开启 |
如果有$header,则开启 |
如果有$header,则开启 |
|
CURLOPT_HEADER |
False |
False |
True |
|
CURLOPT_NOBODY |
false |
False |
true |
|
CURLOPT_POSTFILEDS |
True |
false |
false |
从上表中可以看出:
POST方法:开启POST连接,然后发送POST报文体。关闭HEADER和NOBODY
GET方法:关闭POST相关的选项,关闭NOBODY
HEADER,仅仅只是开启curlopt_httpheader
HEADER方法:开启HEADER和NOBODY,关闭POST相关的选项。
应该说上述三种方法,一个明显的区别是,箱采用什么方法的时候,就开启对应的CURL选项。
CURL_HTTPHEADER与CUROPT_HEADER的区别:
前者是设置HTTP头部信息的一个数组
后者是将头文件的信息以数据流的方式输出。
Curl 采集乱码 gzip 原因及解决方案 utf-8的更多相关文章
- PHP接收GET中文参数乱码的原因及解决方案
方案1: $str = iconv("gb2312","utf-8",$str); 方案2: mb_convert_encoding($str, "u ...
- hive表数据导出到csv乱码原因及解决方案
转载自http://blog.csdn.net/lgdlxc/article/details/42126225 Hive表中的数据使用hive - e"select * from table ...
- php中文乱码问题的终极解决方案汇总
乱码是我们在开发可能经常遇见,也是最让人头疼的一个问题了,下面这篇文章主要介绍了在php开发中,可能遇见中文乱码问题的终极解决方案,文中介绍好几个情况下的解决方法,需要的朋友可以参考借鉴,下面来一起看 ...
- 玩转Windows服务系列——无COM接口Windows服务启动失败原因及解决方案
将VS创建的Windows服务项目编译生成的程序,通过命令行 “服务.exe -Service”注册为Windows服务后,就可以通过服务管理器进行管理了. 问题 通过服务管理器进行启动的时候,发现服 ...
- php curl 采集
curl 采集五个步骤: 1.curl_init()初始化curl 2.curl_setopt()设置传输数据和参数 3.curl_exec()执行传输并获取返回数据 4.curl_errono()返 ...
- PowerDesigner16.5 连64位MySQL,出错:SQLSTATE = IM014。原因及解决方案
- NIOS II CPU复位异常的原因及解决方案
NIOS II CPU复位异常的原因及解决方案 近期在用nios ii做项目时,发现一个奇怪的现象,在NIOS II EDS软件中编写好的代码,烧写到芯片中,第一次能够正常运行,但是当我按下板卡上 ...
- mysql保存中文乱码的原因和解决办法
当你遇到这个mysql保存中文乱码问题的时候,期待找到mysql保存中文乱码的原因和解决办法这样一篇能解决问题的文章是多么激动人心. 也许30%的程序员会选择自己百度,结果发现网友已经贴了很多类 ...
- oracle超出打开游标的最大数的原因和解决方案
oracle超出打开游标的最大数的原因和解决方案 分类: Oracle相关2012-06-05 10:36 6362人阅读 评论(0) 收藏 举报 oracle数据库sqljavasessionsys ...
随机推荐
- linux内核--软中断与tasklet
硬件中断通常都需要在最短的时间内执行完毕,如果将所有硬件中断相关的处理都放在硬件中断处理程序中,那么就达不到这个目的. 通过linux提供的软中断和tasklet,可以将硬件中断处理程序中可以延迟处理 ...
- 探索AutoLayout的本质和解决一些问题
最近频繁使用AutoLayout,记录下自己的一些发现和问题的解决(不是教程) 1.简介 Auto Layout 是苹果在 iOS 6中新引入的布局方式,旨在解决不同尺寸屏幕的适配问题. 屏幕适配工作 ...
- struts2环境搭建和第一个程序
环境搭建 项目目录 导入依赖jar包,如上图lib目录所示. 不同的版本可能会不一样,没关系在tomcat启动时,如果报错java.lang.ClassNotFoundException,我们可以按照 ...
- 我最喜欢的visual studio 2013的新特性
博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:我最喜欢的visual studio 2013的新特性.
- IntelliJ IDEA 配置Jetty
jetty是google app engine 在大量使用的一款服务器软件,不过当然目前还撼动不了tomcat的地位,但是jetty相当轻量级,可以自己灵活定制 资源占用少 ,所以还是有吸引力的,接下 ...
- Android Socket编程基础
前些天写了一个Android手机在局域网内利用Wifi进行文件传输的Demo,其中用到了Socket编程,故此总结(盗了网友的一些图和文字).好久好久没来博客园了~~ 1.什么是Socket? soc ...
- 从零开始学android开发-创建第一个android项目
打开ADT开发工具
- poj 1149 Pigs 网络流-最大流 建图的题目(明天更新)-已更新
题目大意:是有M个猪圈,N个顾客,顾客要买猪,神奇的是顾客有一些猪圈的钥匙而主人MIRKO却没有钥匙,多么神奇?顾客可以在打开的猪圈购买任意数量的猪,只要猪圈里有足够数量的猪.而且当顾客打开猪圈后mi ...
- Big Data 應用:第二季(4~6月)台湾地区Game APP 变动分布趋势图
图表简介: 该示意图表示了台湾地区第二季内所有Game APP类别的分布情形,经由该图表我们可以快速的了解到在这三个月内,哪类型的APP是很稳定:抑或者哪类型的APP是非常不稳定的. 名词解释: 类别 ...
- 核心运营报表无线端数据,pv,uv相关数据,从9月1号开始就没了,为什么?
问题现象截图 核心运营报表 从获取数据的api的地址可以看出: http://data.51buy.com/json.php?biz=statistic&mod=OrderKeyData&am ...