当前位置:首页 > PHP教程 > php应用 > 列表

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

发布:smiling 来源: PHP粉丝网  添加日期:2020-06-23 16:24:59 浏览: 评论:0 

用 file_get_contents() 函数抓取网页会发生乱码现象。有两个原因会导致乱码,一个是编码问题,一个是目标页面开了Gzip,下面说的就是开了Gzip功能如何才能不乱码的方法。

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

请求头信息原始头信息。

  1. Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
  2. Accept-Encoding gzip, deflate 
  3. Accept-Language zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3 
  4. Connection keep-alive 
  5. 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.phpfensi.com; PHPSESSID=888mj4425p8s0m7s0frre3ovc7; __utmc=225240837; __utmb=225240837.1.10.1335411401 
  6. Host www.phpfensi.com 
  7. 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

  1. function curl_get($url$gzip=false){ 
  2.  $curl = curl_init($url); 
  3.  curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 
  4.  curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10); 
  5.  if($gzip) curl_setopt($curl, CURLOPT_ENCODING, "gzip"); // 关键在这里 
  6.  $content = curl_exec($curl); 
  7.  curl_close($curl); 
  8.  return $content

3. 使用gzip解压函数:

  1. function gzdecode($data) {  
  2.   $len = strlen($data);  
  3.   if ($len < 18 || strcmp(substr($data,0,2),"\x1f\x8b")) {  
  4.     return null;  // Not GZIP format (See RFC 1952)  
  5.   }  
  6.   $method = ord(substr($data,2,1));  // Compression method  
  7.   $flags  = ord(substr($data,3,1));  // Flags  
  8.   if ($flags & 31 != $flags) {  
  9.     // Reserved bits are set -- NOT ALLOWED by RFC 1952  
  10.     return null;  
  11.   }  
  12.   // NOTE: $mtime may be negative (PHP integer limitations)  
  13.   $mtime = unpack("V"substr($data,4,4));  
  14.   $mtime = $mtime[1];  
  15.   $xfl   = substr($data,8,1);  
  16.   $os    = substr($data,8,1);  
  17.   $headerlen = 10;  
  18.   $extralen  = 0;  
  19.   $extra     = "";  
  20.   if ($flags & 4) {  
  21.     // 2-byte length prefixed EXTRA data in header  
  22.     if ($len - $headerlen - 2 < 8) {  
  23.       return false;    // Invalid format  
  24.     }  
  25.     $extralen = unpack("v",substr($data,8,2));  
  26.     $extralen = $extralen[1];  
  27.     if ($len - $headerlen - 2 - $extralen < 8) {  
  28.       return false;    // Invalid format  
  29.     }  
  30.     $extra = substr($data,10,$extralen);  
  31.     $headerlen += 2 + $extralen;  
  32.   }  
  33.  
  34.   $filenamelen = 0;  
  35.   $filename = "";  
  36.   if ($flags & 8) {  
  37.     // C-style string file NAME data in header  
  38.     if ($len - $headerlen - 1 < 8) {  
  39.       return false;    // Invalid format  
  40.     }  
  41.     $filenamelen = strpos(substr($data,8+$extralen),chr(0));  
  42.     if ($filenamelen === false || $len - $headerlen - $filenamelen - 1 < 8) {  
  43.       return false;    // Invalid format  
  44.     }  
  45.     $filename = substr($data,$headerlen,$filenamelen);  
  46.     $headerlen += $filenamelen + 1;  
  47.   }  
  48.  
  49.   $commentlen = 0;  
  50.   $comment = "";  
  51.   if ($flags & 16) {  
  52.     // C-style string COMMENT data in header  
  53.     if ($len - $headerlen - 1 < 8) {  
  54.       return false;    // Invalid format  
  55.     }  
  56.     $commentlen = strpos(substr($data,8+$extralen+$filenamelen),chr(0));  
  57.     if ($commentlen === false || $len - $headerlen - $commentlen - 1 < 8) {  
  58.       return false;    // Invalid header format  
  59.     }  
  60.     $comment = substr($data,$headerlen,$commentlen);  
  61.     $headerlen += $commentlen + 1;  
  62.   }  
  63.  
  64.   $headercrc = "";  
  65.   if ($flags & 1) {  
  66.     // 2-bytes (lowest order) of CRC32 on header present  
  67.     if ($len - $headerlen - 2 < 8) {  
  68.       return false;    // Invalid format  
  69.     }  
  70.     $calccrc = crc32(substr($data,0,$headerlen)) & 0xffff;  
  71.     $headercrc = unpack("v"substr($data,$headerlen,2));  
  72.     $headercrc = $headercrc[1];  
  73.     if ($headercrc != $calccrc) {  
  74.       return false;    // Bad header CRC  
  75.     }  
  76.     $headerlen += 2;  
  77.   }  
  78.  
  79.   // GZIP FOOTER - These be negative due to PHP's limitations  
  80.   $datacrc = unpack("V",substr($data,-8,4));  
  81.   $datacrc = $datacrc[1];  
  82.   $isize = unpack("V",substr($data,-4));  
  83.   $isize = $isize[1];  
  84.  
  85.   // Perform the decompression:  
  86.   $bodylen = $len-$headerlen-8;  
  87.   if ($bodylen < 1) {  
  88.     // This should never happen - IMPLEMENTATION BUG!  
  89.     return null;  
  90.   }  
  91.   $body = substr($data,$headerlen,$bodylen);  
  92.   $data = "";  
  93.   if ($bodylen > 0) {  
  94.     switch ($method) {  
  95.       case 8:  
  96.         // Currently the only supported compression method:  
  97.         $data = gzinflate($body);  
  98.         break;  
  99.       default:  
  100.         // Unknown compression method  
  101.         return false;  
  102.     }  
  103.   } else {  
  104.     // I'm not sure if zero-byte body content is allowed.  
  105.     // Allow it for now...  Do nothing...  
  106.   }  
  107.  
  108.   // Verifiy decompressed size and CRC32:  
  109.   // NOTE: This may fail with large data sizes depending on how  
  110.   //       PHP's integer limitations affect strlen() since $isize  
  111.   //       may be negative for large sizes.  
  112.   if ($isize != strlen($data) || crc32($data) != $datacrc) {  
  113.     // Bad format!  Length or CRC doesn't match!  
  114.     return false;  
  115.   }  
  116.   return $data;  

使用:

  1. $html=file_get_contents('https://www.phpfensi.com/'); 
  2. $html=gzdecode($html); 

就介绍这三个方法,应该能解决大部分gzip引起的抓取乱码问题了。

Tags: file_get_contents

分享到: