php file_get_contents抓取Gzip网页乱码的三种解决方法


Posted in PHP onNovember 12, 2013

把抓取到的内容转下编码即可($content=iconv("GBK", "UTF-8//IGNORE", $content);),我们这里讨论的是如何抓取开了Gzip的页面。怎么判断呢?获取的头部当中有Content-Encoding: gzip说明内容是GZIP压缩的。用FireBug看一下就知道页面开了gzip没有。下面是用firebug查看我的博客的头信息,Gzip是开了的。

请求头信息原始头信息
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Connection keep-alive
Cookie __utma=225240837.787252530.1317310581.1335406161.1335411401.1537; __utmz=225240837.1326850415.887.3.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=%E4%BB%BB%E4%BD%95%E9%A1%B9%E7%9B%AE%E9%83%BD%E4%B8%8D%E4%BC%9A%E9%82%A3%E4%B9%88%E7%AE%80%E5%8D%95%20site%3Awww.nowamagic.net; PHPSESSID=888mj4425p8s0m7s0frre3ovc7; __utmc=225240837; __utmb=225240837.1.10.1335411401
Host www.nowamagic.net
User-Agent Mozilla/5.0 (Windows NT 5.1; rv:12.0) Gecko/20100101 Firefox/12.0

下面介绍一些解决方案:

1. 使用自带的zlib库
如果服务器已经装了zlib库,用下面的代码可以轻易解决乱码问题。

$data = file_get_contents("compress.zlib://".$url);

2. 使用CURL代替file_get_contents

function curl_get($url, $gzip=false){
 $curl = curl_init($url);
 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
 curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10);
 if($gzip) curl_setopt($curl, CURLOPT_ENCODING, "gzip"); // 关键在这里
 $content = curl_exec($curl);
 curl_close($curl);
 return $content;
}

3. 使用gzip解压函数

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

使用:
$html=file_get_contents('https://3water.com/');
$html=gzdecode($html);

就介绍这三个方法,应该能解决大部分gzip引起的抓取乱码问题了。
PHP 相关文章推荐
php&amp;java(一)
Oct 09 PHP
php设计模式 Singleton(单例模式)
Jun 26 PHP
基于PHP Web开发MVC框架的Smarty使用说明
Apr 19 PHP
PHP 关于访问控制的和运算符优先级介绍
Jul 08 PHP
PHP输出英文时间日期的安全方法(RFC 1123格式)
Jun 13 PHP
ThinkPHP采用实现三级循环代码实例
Jul 18 PHP
php 模拟 asp.net webFrom 按钮提交事件实例
Oct 13 PHP
PHP产生不重复随机数的5个方法总结
Nov 12 PHP
php找出指定范围内回文数且平方根也是回文数的方法
Mar 23 PHP
thinkPHP框架可添加js事件的分页类customPage.class.php完整实例
Mar 16 PHP
php删除数组指定元素实现代码
May 03 PHP
laravel5.4利用163邮箱发送邮件的步骤详解
Sep 22 PHP
CodeIgniter使用phpcms模板引擎
Nov 12 #PHP
php用正则表达式匹配URL的简单方法
Nov 12 #PHP
CodeIgniter基本配置详细介绍
Nov 12 #PHP
PHP URL路由类实例
Nov 12 #PHP
PHP set_error_handler()函数使用详解(示例)
Nov 12 #PHP
php inc文件使用的风险和注意事项
Nov 12 #PHP
php防止SQL注入详解及防范
Nov 12 #PHP
You might like
总集篇&特番节目先行播出!《SAO Alicization War of Underworld》第2季度TV动画4月25日放送!
2020/03/06 日漫
Smarty中常用变量操作符汇总
2014/10/27 PHP
php绘制圆形的方法
2015/01/24 PHP
php禁用cookie后session设置方法分析
2016/10/19 PHP
Yii2框架中使用PHPExcel导出Excel文件的示例
2017/08/09 PHP
JS高级调试技巧:捕获和分析 JavaScript Error详解
2014/03/16 Javascript
jQuery实现的网页右下角tab样式在线客服效果代码
2015/10/23 Javascript
JavaScript Date对象详解
2016/03/01 Javascript
解析js如何获取css样式
2016/12/11 Javascript
基于Javascript实现的不重复ID的生成器
2016/12/25 Javascript
Vue 过渡(动画)transition组件案例详解
2017/01/22 Javascript
vue组件实现弹出框点击显示隐藏效果
2020/10/26 Javascript
linux 后台运行node服务指令方法
2018/05/23 Javascript
记一次vue-webpack项目优化实践详解
2019/02/17 Javascript
浅谈JS的原型和继承
2019/05/08 Javascript
axios异步提交表单数据的几种方法
2019/08/11 Javascript
从表单校验看JavaScript策略模式的使用详解
2020/10/17 Javascript
python通过yield实现数组全排列的方法
2015/03/18 Python
Django开发中复选框用法示例
2018/03/20 Python
python实现对csv文件的列的内容读取
2018/07/04 Python
Django添加favicon.ico图标的示例代码
2018/08/07 Python
python 抓包保存为pcap文件并解析的实例
2019/07/23 Python
Python大数据之网络爬虫的post请求、get请求区别实例分析
2019/11/16 Python
在tensorflow中实现去除不足一个batch的数据
2020/01/20 Python
浅析Python面向对象编程
2020/07/10 Python
CSS3之背景尺寸Background-size使用介绍
2013/10/14 HTML / CSS
HTML5 canvas基本绘图之绘制线段
2016/06/27 HTML / CSS
密封类可以有虚函数吗
2014/08/11 面试题
介绍一下Make? 为什么使用make
2013/12/08 面试题
社区敬老月活动实施方案
2014/02/17 职场文书
出生公证书样本
2014/04/04 职场文书
教书育人演讲稿
2014/09/11 职场文书
运动会广播稿50字-100字
2014/10/11 职场文书
2015年护士医德医风自我评价
2015/03/03 职场文书
2016年寒假社会实践活动总结
2015/03/27 职场文书
物流业务员岗位职责
2015/04/03 职场文书