使用Node.js写爬虫的一些经验分享

💡 注意,这是个人经验分享,不是一份完整的教程,并不能帮你从零到一学会怎么写爬虫。

💡 关于写爬虫一些比较重要的知识点:HTTP 协议、抓包与调试、Promise、事件循环机制、一定的法律意识(认真脸

⚠️ 爬虫不是越快越好,不影响目标网站是最重要的前提。不然你火力全开,开了 N 个线程直接把目标网站打崩了,这和 DDOS 攻击有什么区别呢?这可简直太刑了~

撇开上面提到的最后一个,个人认为最重要的其实还是自我解决问题的能力,碰到问题的时候至少能根据搜索引擎或者是别的什么渠道,定位到大概问题是什么,应该怎么样去解决,不然可能会经常卡死卡死卡死。

Node.js 适合写爬虫吗?

扯回正题,Node.js 还是蛮适合写爬虫的。众所周知,Node.js 得益于它的异步 I/O^(Node.js 采用了异步 I/O 模型,这意味着当一个请求需要等待 I/O 操作完成时,Node.js 不会阻塞线程,而是继续处理其他请求。这有助于防止请求阻塞,从而提高了系统的并发性能。)^ 和事件驱动机制^(Node.js 基于事件驱动的架构,对于每个请求,Node.js 都会生成一个事件,并在请求完成后发布该事件。这有助于高效地管理请求,从而提高系统的并发性能。)^,非常适合处理 I/O 密集型的任务,而不善于处理 CPU 密集的任务。而爬虫是做什么呢?在不影响目标网站的前提下,尽可能快的将所需的资源取回来,整个过程很少能碰到需要 CPU 大量运算的场景,先天合拍。

而在某些场景下,如果目标站点是 SPA 应用,没进行服务端渲染,同时你又找不到或者是无法利用对应的 API 接口,这时候还可以祭出无头浏览器(如 [[Puppeteer]])这个大杀器。虽然相对于直接爬 API 慢了一点,但是更加通用。

用不用框架

之前写爬虫的时候也使用过一些框架,如 Crawler(星星比较多,目前好歹还在维护更新)。使用下来我的感受是如果爬虫比较简单,层级结构分明,的确可以提升效率。但我用的还是不太爽,因为框架设计要写回调,层级一深就很难受。

所以,如果你的爬虫比较复杂,还有着和其他业务的交叉,可以考虑自己写。主要就是发请求、处理响应、任务队列、限制速率、并发请求这些东西,而且并发请求之类的强烈建议不要滥用,不要影响到目标站点的运行。

请求与抓包

最基本的发 HTTP 请求就不用说了,got、node-fetch、super-agent、axios 都可以,自己哪个用的多,哪个用的习惯就用哪个,建议请求提前封装好接口,方便扩展,然后需要的时候直接调用就好。最好不要一股脑的全塞进爬虫的逻辑里,看着头大 = =。

既然都要发请求了,那你肯定得知道往哪里发,参数是什么吧,所以还得提前抓包,获取到需要的一些信息。PC 端用的比较多的可能就是 Fiddler,Charles 这些。网上关于这些工具的使用教程并不少,这里不再赘述。需要注意的是现在的网站基本都是 HTTPS 协议了,配置的时候记得不要忘记导入证书,不然解密不了 HTTPS 的内容的。

上面的工具虽然也可以配置无线网络的代理去抓手机上的包,但是有些 App 不鸟你的配置啊,你配置的代理我就是不走(比如微信 = =)。想要抓到这种应用的包,可以配置成 VPN 的形式。

Android 平台上可以直接使用 HttpCanary 这个应用。需要注意的是这个应用已经停更了,对高版本的 Android 可能不太友好,可以尝试网络上找找 MOD 版本的,因为版本众多,所以我无法给出一个具体的建议,只能各位自己找找试试了。iOS 平台上我不太熟悉,但想必也有类似的工具,只好麻烦各位自行检索相关资源。

数据处理

接下来就是发请求,然后写爬虫的具体逻辑。一般都是获取列表页,再获取详情页,然后再根据获取的参数继续获取别的数据,这样下层层下去,环环相扣。各个任务之间多少免不了要进行通讯,可以考虑使用 发布订阅模式​,直接用 Node.js 的 EventEmitter​ 就行。

接下来就是要将爬取的数据进行存储了,在此之前,还需要提一下日志。项目跑起来不可能一帆风顺,多少会遇到点问题的。想要快速的定位问题,肯定少不了打日志,而且是能够事后查询的日志。所以建议不要图省事直接用 console.log​,多少用一个日志库,将日志写入到能持久存储的地方。至于日志库, winston pino.js 都可以,wiston 生态更好,pino.js 主打快。

接下来就是存储爬取的数据,如果是图片文件之类的,可以直接写入到本地。而如果是一些格式化好的数据,建议存储在 [[MongoDB]] 中,数据不需要怎么处理就可以直接丢进去,Node.js 和 MongoDB 也蛮合拍的。

💡 注意在存储之前考虑好,自己保存的这些数据能不能满足需求,需不需要将请求参数或者其他的的东西也存进去。

存储完数据之后,可能还需要对数据进行清洗或者转换,如果使用的是 MongoDB 并且不太熟悉,个人建议以 官方文档 为主,以 Google 和 Stack Overflow 为辅,常见的操作一般都能解决。

基本就是这样了,虽然可能还有很多琐碎的地方没有提及到,但大体是这样没错~~~

如果后续想起来别的方面, 再进行补充~~~