有时候用 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. MAC和windows开发操作系统环境,解决Maven工程中报 Missing artifact jdk.tools:jdk.tools

    同事使用的是苹果mac,而我们其他人的开发环境是windows jdk1.8 导致同事从git上pull下来的工程,pom文件是直接报错的, windows下的pom文件设置是这样的: <dep ...

  2. Python学习第二弹

    昨天补充: 编码: Unicode ; utf-8 ; GBK       关系:   关键字:1. continue 终止当前循环,进行下一次循环 2. break      终止循环 题6解法2: ...

  3. Python3爬虫(十一) 爬虫与反爬虫

    Infi-chu: http://www.cnblogs.com/Infi-chu/ 一.重要概念 二.爬虫反爬虫进化论

  4. Android使用butterknife注解出现nullPointerException解决

    1.下载butterknife加入到你的libs中,构建到你的项目中,此时还不能注解成功,必须进行2配置 2.选择你的项目右键---->properties----->java compi ...

  5. 3468-A Simple Problem with Integers 线段树(区间增减,区间求和)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 110077 ...

  6. 现代web开发需要学习的15大技术

    现代Web开发需要学习的15大技术 2016-06-08 13:08 快进到现在,我发现现代web开发再一次将发生压倒性的改变.信息资讯的铺天盖地令人迷惑,尤其对于初学者而言.首要原因是新的框架,例如 ...

  7. 网易云terraform实践

    此文已由作者王慎为授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 一.terraform介绍 随着应用上云的常态化,资源栈动态管理的需求对用户也变得更加急切.资源编排(Res ...

  8. 玩转Vim-札记(二)

    玩转Vim-札记(二) 距上篇博文已有一周有余,上次主要介绍了编辑器之神Vim的起源.安装并介绍了两种模式以及一些简单的操作.本次将继续对Vim的使用进行介绍. 登堂入室 首先接着说移动吧: 0 → ...

  9. adb常用命令(手机测试)

                                                   ADB安装与常用命令详解 一.ADB意义 adb的全称为Android Debug Bridge,就是起到 ...

  10. 从底层带你理解Python中的一些内部机制

    下面博文将带你创建一个字节码级别的追踪API以追踪Python的一些内部机制,比如类似YIELDVALUE.YIELDFROM操作码的实现,推式构造列表(List Comprehensions).生成 ...