上周尝试用teleport采集一个小站(偶尔玩一下,绝无恶意),结果发现采集到的第一个文件就是乱码,当然无法继续了。后来又用wget和curl尝试了一下,发现得到的同样是乱码。
于是,开始初步分析了一下目标站点,发现也没有什么特殊的a链接或js设置,cookie也没有啥特殊的,然后封IP更不可能了,因为浏览器都是正常解析的,唯独teleport、wget和curl不可用。所以,我怀疑乱码是因为打开的是压缩包,果断右键wget到的文件属性,显示是gzip文件。(尽管,我现在还不知道目标站的web server如何配置的gzip,让wget只能得到gzip压缩包文件,而浏览器可以正常解析;因为,我在本地apache配置了gzip压缩,然后尝试用wget下载本地页面,但没有得到gzip压缩包文件,这个随后再说)
今天一个偶然的机会,调试curl配置项,用到了CURLOPT_ENCODING设置项:
PHP
curl_setopt($curl, CURLOPT_ENCODING, ''); //可解压缩gzip、deflate等压缩文件
/**
*php.net给出的解释
*CURLOPT_ENCODING
* The contents of the "Accept-Encoding: " header. This enables decoding of the response.
* Supported encodings are "identity", "deflate", and "gzip". If an empty string, "", is set, a
* header containing all supported encoding types is sent.
*/
1
2
3
4
5
6
7
8curl_setopt($curl,CURLOPT_ENCODING,'');//可解压缩gzip、deflate等压缩文件
/**
*php.net给出的解释
*CURLOPT_ENCODING
* The contents of the "Accept-Encoding: " header. This enables decoding of the response.
* Supported encodings are "identity", "deflate", and "gzip". If an empty string, "", is set, a
* header containing all supported encoding types is sent.
*/
发现输出的乱码消失了。
后来在搜索CURLOPT_ENCODING关键词的时候,发现其他人也遇到了这个问题:http://www.lao8.org/article_1570/CURLOPT_ENCODING
关于上面【随后再说】的续写:
为什么会出现浏览器能正常解释,而wget和默认参数的curl请求得到的都是无法文本解析的gzip文件呢?
答案就是目标站强制输出了gzip压缩。
下面说几个关于gzip压缩的问题:
1、Apache服务器的gzip压缩
Apache的gzip压缩是”智能“压缩,简单说就是判断浏览器是否支持gzip(根据:Accept-Encoding: gzip, deflate请求头信息),支持则返回gzip压缩输出,否则,原格式返回。
Apache支持gzip和deflate两个模块,都返回gzip压缩格式,区别是gzip压缩率更高,但cpu占用更高;deflate压缩性能更好,是专为web压缩设计的,在较高并发的情况下,比gzip更有优势。
官方一点的说明如下:
1. Web服务器接收到浏览器的HTTP请求后,检查浏览器是否支持HTTP压缩(Accept-Encoding 信息);
2. 如果浏览器支持HTTP压缩,Web服务器检查请求文件的后缀名;
3. 如果请求文件是HTML、CSS等静态文件,Web服务器到压缩缓冲目录中检查是否已经存在请求文件的最新压缩文件;
4. 如果请求文件的压缩文件不存在,Web服务器向浏览器返回未压缩的请求文件,并在压缩缓冲目录中存放请求文件的压缩文件;
5. 如果请求文件的最新压缩文件已经存在,则直接返回请求文件的压缩文件;
6. 如果请求文件是动态文件,Web服务器动态压缩内容并返回浏览器,压缩内容不存放到压缩缓存目录中。
1
2
3
4
5
61.Web服务器接收到浏览器的HTTP请求后,检查浏览器是否支持HTTP压缩(Accept-Encoding信息);
2.如果浏览器支持HTTP压缩,Web服务器检查请求文件的后缀名;
3.如果请求文件是HTML、CSS等静态文件,Web服务器到压缩缓冲目录中检查是否已经存在请求文件的最新压缩文件;
4.如果请求文件的压缩文件不存在,Web服务器向浏览器返回未压缩的请求文件,并在压缩缓冲目录中存放请求文件的压缩文件;
5.如果请求文件的最新压缩文件已经存在,则直接返回请求文件的压缩文件;
6.如果请求文件是动态文件,Web服务器动态压缩内容并返回浏览器,压缩内容不存放到压缩缓存目录中。
2、Php文件的gzip压缩
修改php.ini配置:
zlib.output_compression = On
zlib.output_compression_level = 5
;建议参数值是1~5,6以实际压缩效果提升不大,cpu占用却是几何增长
1
2
3zlib.output_compression=On
zlib.output_compression_level=5
;建议参数值是1~5,6以实际压缩效果提升不大,cpu占用却是几何增长
仅对.php文件有效,对html、css、js文件无效。
3、php控制服务器端输出强制为gzip压缩
php内置gzip压缩函数,强制压缩输出。
示例代码:
PHP
header("Content-Encoding: gzip");
// header("Vary: Accept-Encoding");
header("Content-Length: ".strlen($html));
echo gzencode($html);
1
2
3
4
5<?php
header("Content-Encoding: gzip");
// header("Vary: Accept-Encoding");
header("Content-Length: ".strlen($html));
echogzencode($html);
当然了,php也可以根据请求头信息是否支持gzip进行”智能“压缩。
PHP
if(strstr($_SERVER["HTTP_ACCEPT_ENCODING"],"gzip"))
1if(strstr($_SERVER["HTTP_ACCEPT_ENCODING"],"gzip"))
如果有,则返回压缩,否则,返回正常格式。不过,强制压缩,可以从一定程度上防止被采集。