爬虫,说实话我不会,我只会请求互联网的资源

免责声明:以下纯属杜撰,如有雷同,概不负责

稍微有点服务端知识的人,应该都知道爬虫。简单理解就是用程序代替人工去控制请求,然后拿回自己想要的数据。

开发准备

分析你期望的数据,是不是直接是在接口里的。如果是,那就简单很多,如果不是,那暴力点直接爬页面

工具

使用 Nodejs 开发,用到的包有 cheerio (服务器端的 JQ,便捷解析网页提取内容),request(请求器),async 并发控制

// async
async.mapLimit(res.data, 5, function () {
  // do something
}, (err, results) => {
  if (err) throw err
})
// cheerio
const $ = cheerio.load(res)

const temp = $('#ID').html()

关键难点1:高效

正所谓,天下武功为快不破。

一开始,有多少请求,一个循环全发出去了。量少没事,量多了,先不说对方服务器把你给 Ban 了,可能你自己的路由器先给死机了。怎么办?改

使用 async 控制了并发数量,即当前最大存在多少请求,有空闲时才会继续下个请求。

关键难点2:穿越'对面'的封锁线

还是数量的问题。async 模块包,虽然可以控制最大的并发请求数,不过当请求特别快的时候,几十ms 就回包了,也就有可能造成 1s 钟发大几十条数据。这样,明显危险,很不幸,我就踩到雷了。

怎么解决呢, 上代理。原理就是从单 IP 请求,变成可能是大量 IP 共同完成了整体任务

关键难点3:垃圾代理的抉择

目的当然是便宜又好用,当然这就是想想,研究了几家代理,发现适合自己这款爬虫的,都有一个限制,每秒只能发送几条。

解决方法,使用了全局的计时器,每次发请求同时计算下次可执行时间点 A。当请求回包时,

当前时间 <= A , 计算差值,并使用 setTimeout 延迟处理,这里结合了 async await, 同步模式
当前时间 > A , 直接执行

即使是这样子,代理依旧不给力,可能请求失败,或者延迟颇高。只好安排上错误重试机制了,会尝试 5 次,五次不行 拜拜

也许由于知识面的欠缺,接入代理,真不是一件容易的事。而且为了妥协,将全异步调用的代码,改为了同步模式

总结

爬虫写了很久了,目前也稳定使用中。考虑到这次写的相对复杂,于是记录了这篇文章。是否还有更复杂的,肯定是有的,据我所知,还有网站为了对抗爬虫,显示的内容和你爬到的可能还不一致,需要你去转化成真实数据等等

对自己过往的知识做了一次串联