作为一名 web 开发人员,时不时爬爬别人家的网站还是很有趣的。
其实,爬一个网站的数据也是爬取者和被爬取者的一种攻防较量:一般情况下,被爬取者总是会想方设法地阻止爬取者爬取自家网站数据。
于是,一些网站就会采取一些措施来阻止非正常访问:
- 某某关键接口只能每分钟调用若干次;
- 某某 IP 访问网站太频繁,直接拒绝掉该 IP 发过来的请求。
当然,这些措施都只是治标不治本,不能从根本上杜绝自己网站数据被爬。
从爬取者的角度来看,要突破层层限制,拿到目标网站的数据,还是要做一些事情的:
- 如果要爬取的目标网页需要登录才能访问到,那么可以采用 phantomjs 来简化掉 session 的处理;
- 在爬取的过程中,如果发现服务器从某个时刻开始一直拒绝掉自己的请求,那么就要怀疑自己的 IP 是否被屏蔽掉了,或者某个接口是否访问太频繁了;
- 对于有 IP 限制策略的网站,尽量模拟正常用户访问,频率不要太快,最好做多个节点来爬取。
等等,有点偏题了!下面进入正轨:
在初次写爬虫代码的时候,很容易遇到解析出来的数据是乱码的问题:
面对这些乱码,如何解决呢?
注意 HTTP 响应的头部
留意一下 HTTP 响应的头部是否有用 gzip 压缩过:
|
|
如果有这种字眼,那么响应正文部分就是使用 gzip 压缩过的,在拿到这种压缩过的数据之后,要先解压。
Node.js 中,提供了 zlib 模块,用于处理 gzip 相关的操作。对于解压 gzip ,可以这样做:
|
|
注意文本编码
拿着最终 gzip 解压出来的数据,开心的去进行后续处理,结果继续乱码,为什么会这样?
Node.js 里面默认字符串是 utf-8
编码的,如果 gzip 解压出来的数据不是 utf-8
编码的话,那么把这堆 buffer 数据转换成字符串的时候就可能产生乱码。 到目前为止,Node.js 内置支持的解码方式很有限,只能依靠一些第三方模块进行某些文本解码。
怎么办呢?
留意一下响应头当中的 Content-Type
部分,如果 charset 是非 utf-8
的话,那就要考虑继续对数据进行解码了。
对于中文网站,可能会使用 GBK
或者 GB2312
进行编码,对于此种场景,需要用到第三方的解码工具,此处选用了 iconv-lite
。解码过程如下:
|
|
这样,就拿到了最终想要的文本数据。