有时候用 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. keil5 mdk调用外部编辑器notepad++、sublime3、VSCode总结

    1.打开keil主界面,点击菜单栏Tools菜单,选择如下图所示的选项. 2.点击如下图所示的菜单上红笔标注的地方,给这个工具命名,如notepad++.sublime3.vscode等,如下图, 并 ...

  2. ruby 数据类型Range

    范围(Range)无处不在:a 到 z. 0 到 9.等等.Ruby 支持范围,并允许我们以不同的方式使用范围: 作为序列的范围 作为条件的范围 作为间隔的范围 作为序列的范围 (1..5) #==& ...

  3. 015---Django的forms组件

    Django form表单   Form介绍 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用 ...

  4. (数据科学学习手札27)sklearn数据集分割方法汇总

    一.简介 在现实的机器学习任务中,我们往往是利用搜集到的尽可能多的样本集来输入算法进行训练,以尽可能高的精度为目标,但这里便出现一个问题,一是很多情况下我们不能说搜集到的样本集就能代表真实的全体,其分 ...

  5. TreeMap与LinkedHashMap的区别

    TreeMap是根据元素的内部比较器进行排序的,它可以根据key值的大小排序: LinkedHashMap是保持存放顺序的. TreeMap采用红黑树算法,遍历效率高: LinkedHashMap采用 ...

  6. CentOS 7 systemd添加自定义系统服务

    systemd: CentOS 7的服务systemctl脚本存放在:/usr/lib/systemd/,有系统(system)和用户(user)之分,即:/usr/lib/systemd/syste ...

  7. (转) Sqoop使用实例讲解

    原博客地址:http://blog.csdn.net/evankaka 摘要:本文主要讲了笔者在使用sqoop过程中的一些实例 一.概述与基本原理 Apache Sqoop(SQL-to-Hadoop ...

  8. ArcPy:GeoJSON转ArcGIS Geometry

    import arcpy geojson = {"type":"Polygon","coordinates":[[[120.81878662 ...

  9. Maven初步接触

    最近随着搜资料,网上这样的字眼越来越多,我了解到这是构建项目的一种方式,于是准备简单看一下 首先粘几篇文章,作为学习的初步资料 Maven入门 http://blog.csdn.net/prstaxy ...

  10. Android OpenStreetMap(OSM) 使用 osmbonuspack 进行导航

    关于OpenStreetMap的介绍,国内还是很少,csdn上面有一篇,写的不错,我也就不再做重复的事情了. 这里贴出链接地址:http://blog.csdn.net/mad1989/article ...