有时候用 file_get_contents() 函数抓取网页会发生乱码现象。有两个原因会导致乱码,一个是编码问题,一个是目标页面开了Gzip。

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

1 请求头信息原始头信息
2 Accept  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
3 Accept-Encoding gzip, deflate
4 Accept-Language zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
5 Connection  keep-alive
6 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
7 Host    www.nowamagic.net
8 User-Agent  Mozilla/5.0 (Windows NT 5.1; rv:12.0) Gecko/20100101 Firefox/12.0

下面介绍一些解决方案:

1. 使用自带的zlib库

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

1 $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;
9 }

3. 使用gzip解压函数

001 function gzdecode($data) {
002   $len = strlen($data);
003   if ($len < 18 || strcmp(substr($data,0,2),"\x1f\x8b")) {
004     return null;  // Not GZIP format (See RFC 1952)
005   }
006   $method = ord(substr($data,2,1));  // Compression method
007   $flags  = ord(substr($data,3,1));  // Flags
008   if ($flags & 31 != $flags) {
009     // Reserved bits are set -- NOT ALLOWED by RFC 1952
010     return null;
011   }
012   // NOTE: $mtime may be negative (PHP integer limitations)
013   $mtime = unpack("V", substr($data,4,4));
014   $mtime = $mtime[1];
015   $xfl   = substr($data,8,1);
016   $os    = substr($data,8,1);
017   $headerlen = 10;
018   $extralen  = 0;
019   $extra     = "";
020   if ($flags & 4) {
021     // 2-byte length prefixed EXTRA data in header
022     if ($len - $headerlen - 2 < 8) {
023       return false;    // Invalid format
024     }
025     $extralen = unpack("v",substr($data,8,2));
026     $extralen = $extralen[1];
027     if ($len - $headerlen - 2 - $extralen < 8) {
028       return false;    // Invalid format
029     }
030     $extra = substr($data,10,$extralen);
031     $headerlen += 2 + $extralen;
032   }
033  
034   $filenamelen = 0;
035   $filename = "";
036   if ($flags & 8) {
037     // C-style string file NAME data in header
038     if ($len - $headerlen - 1 < 8) {
039       return false;    // Invalid format
040     }
041     $filenamelen = strpos(substr($data,8+$extralen),chr(0));
042     if ($filenamelen === false || $len - $headerlen - $filenamelen - 1 < 8) {
043       return false;    // Invalid format
044     }
045     $filename = substr($data,$headerlen,$filenamelen);
046     $headerlen += $filenamelen + 1;
047   }
048  
049   $commentlen = 0;
050   $comment = "";
051   if ($flags & 16) {
052     // C-style string COMMENT data in header
053     if ($len - $headerlen - 1 < 8) {
054       return false;    // Invalid format
055     }
056     $commentlen = strpos(substr($data,8+$extralen+$filenamelen),chr(0));
057     if ($commentlen === false || $len - $headerlen - $commentlen - 1 < 8) {
058       return false;    // Invalid header format
059     }
060     $comment = substr($data,$headerlen,$commentlen);
061     $headerlen += $commentlen + 1;
062   }
063  
064   $headercrc = "";
065   if ($flags & 1) {
066     // 2-bytes (lowest order) of CRC32 on header present
067     if ($len - $headerlen - 2 < 8) {
068       return false;    // Invalid format
069     }
070     $calccrc = crc32(substr($data,0,$headerlen)) & 0xffff;
071     $headercrc = unpack("v", substr($data,$headerlen,2));
072     $headercrc = $headercrc[1];
073     if ($headercrc != $calccrc) {
074       return false;    // Bad header CRC
075     }
076     $headerlen += 2;
077   }
078  
079   // GZIP FOOTER - These be negative due to PHP's limitations
080   $datacrc = unpack("V",substr($data,-8,4));
081   $datacrc = $datacrc[1];
082   $isize = unpack("V",substr($data,-4));
083   $isize = $isize[1];
084  
085   // Perform the decompression:
086   $bodylen = $len-$headerlen-8;
087   if ($bodylen < 1) {
088     // This should never happen - IMPLEMENTATION BUG!
089     return null;
090   }
091   $body = substr($data,$headerlen,$bodylen);
092   $data = "";
093   if ($bodylen > 0) {
094     switch ($method) {
095       case 8:
096         // Currently the only supported compression method:
097         $data = gzinflate($body);
098         break;
099       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;
117 }

使用:

1 $html=file_get_contents('http://www.nowamagic.net/librarys/veda/');
2 $html=gzdecode($html);

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

如何抓取开了gzip的网页的更多相关文章

  1. 简易数据分析 12 | Web Scraper 翻页——抓取分页器翻页的网页

    这是简易数据分析系列的第 12 篇文章. 前面几篇文章我们介绍了 Web Scraper 应对各种翻页的解决方法,比如说修改网页链接加载数据.点击"更多按钮"加载数据和下拉自动加载 ...

  2. htmlunit抓取js执行后的网页源码

    上次我不是写了一个自动抓取博客访问量吗 (点击打开链接) 可是昨天晚上我又运行的时候,发现不能用了.. 运行了几次 发现使用URLConnection 得到的网页源码和浏览器直接查看的不同. URLC ...

  3. Java HttpURLConnection 抓取网页内容 解析gzip格式输入流数据并转换为String格式字符串

    最近GFW为了刷存在感,搞得大家是头晕眼花,修改hosts 几乎成了每日必备工作. 索性写了一个小程序,给办公室的同事们分享,其中有个内容 就是抓取网络上的hosts,废了一些周折. 我是在一个博客上 ...

  4. Scrapy爬虫框架教程(四)-- 抓取AJAX异步加载网页

    欢迎关注博主主页,学习python视频资源,还有大量免费python经典文章 sklearn实战-乳腺癌细胞数据挖掘 https://study.163.com/course/introduction ...

  5. Python3抓取javascript生成的html网页

    用urllib等抓取网页,只能读取网页的静态源文件,而抓不到由javascript生成的内容. 究其原因,是因为urllib是瞬时抓取,它不会等javascript的加载延迟,所以页面中由javasc ...

  6. 网络包抓取开发包 Npcap

    Npcap 是 Nmap 项目的网络包抓取库在 Windows 下的版本. Npcap 是致力于采用 Microsoft Light-Weight Filter (NDIS 6 LWF) 技术和 Wi ...

  7. python抓取历年特码开奖记录

    背景: 小时候,有种游戏,两个主人公:白XX和曾XX,每个家庭把他俩像活菩萨一样供着,供他们吃,供他们穿 做生意的老板为了这两位活菩萨,关门大吉 农民为了这两位活菩萨卖牛卖田变卖家产 做官的为了这两位 ...

  8. 如何让Python爬虫一天抓取100万张网页

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 王平 源自:猿人学Python PS:如有需要Python学习资料的 ...

  9. Java---网络蜘蛛-网页邮箱抓取器~源码

    刚刚学完Socket,迫不及待的做了这个网页邮箱抓取~~~ 现在有越来越多的人热衷于做网络爬虫(网络蜘蛛),也有越来越多的地方需要网络爬虫,比如搜索引擎.资讯采集.舆情监测等等,诸如此类.网络爬虫涉及 ...

随机推荐

  1. 【Hbase一】基础

    此笔记仅用于作者记录复习使用,如有错误地方欢迎留言指正,作者感激不尽,如有转载请指明出处 Hbase基础 Hbase基础 Hbase定义 行存储 v s 列存储 Hbase数据模型 Hbase物理模型 ...

  2. Hive初识(三)

    根据用户的需求创建视图.可以将任何结果集数据保存为一个视图.视图在Hive的用法和SQL视图用法相同.它是一个标准的RDBMS概念.我们可以在视图上执行所有DML操作. 创建一个试图 可以创建一个试图 ...

  3. python -pickle模块、re模块学习

    pickel模块 import pickle #pickle可以将任何数据类型序列化,json只能列表字典字符串数字等简单的数据类型,复杂的不可以 #但是pickle只能在python中使用,json ...

  4. 4-oracle11g安装

    1.导入安装包,解压 [root@ocp Desktop]# unzip p10404530_112030_Linux-x86-64_1of7.zip [root@ocp Desktop]# unzi ...

  5. SPOJ SUBLEX

    SUBLEX - Lexicographical Substring Search 链接 题意 求第k小的子串.相同的算一个. 分析 建立后缀自动机,在后缀自动机上从一个点经过trans,到另一个点, ...

  6. PIC32MZ 通过U盘在线升级 -- USB Host bootloader

    了解bootloader的实现,请加QQ: 1273623966(验证填bootloader); 欢迎咨询或定制bootloader; 我的博客主页 www.cnblogs.com/geekygeek ...

  7. java反射操作类方法与属性

    package com.fanshe.test; public class User { private int age; private String email; private String u ...

  8. es6中类的注意事项

    class Circle { constructor(radius) { this.radius = radius; Circle.circlesMade++; }; static draw(circ ...

  9. 用gradle编译任意结构的Android项目

    ## 需求 * 继续用`Eclipse`项目的结构,但是使用`gradle`编译,或者说任意的项目结构进行编译. ## 解决方案 1. Android studio的项目结构 1. Android S ...

  10. 实用的placeholder插件,兼容IE下的placeholder,jquery插件

    placeholder在IE下无法兼容 ,下面的插件很好的处理了这个问题,拿去不谢 /* * jQuery placeholder, fix for IE6,7,8,9 * @website itmy ...