笔记:「饭否精选」微信小程序(二)- 爬虫部分


前言

「饭否精选」的数据位置

「饭否精选」的数据供稿地址在 http://blog.fanfou.com/digest/ 目录下,首先输出的是 index 索引内容: json 供稿链接,和文件名 index 暗示的一样,这个供稿的内容阐述了当前有多少「精选」内容,和对应日期的精选内容具体的位置,截取部分数据如下:

其中包含「精选」的两种类型: - 一种是 daily.json 为后缀的「每日精选」; - 另一种是 weekly.json 的「每周精选」。

要获取对应日期的具体内容就是拼接上文提到的根目录的链接,比如说第一条日期为 2017-05-30 的就是 http://blog.fanfou.com/digest/json/2017-05-30.daily.json

微信小程序的 HTTPS 请求限制

虽然在测试环境下有选项可以关闭、便于测试调试,但微信开发中绕不过去的一点是上线的小程序只能发送 HTTPS 请求,而制作「饭否精选」小程序的时候饭否还没支持 HTTPS。由于这一点,为了可以顺利获得数据,绕了圈写了个爬虫,将数据保存到自己的伺服器上(最后选择 LeanCloud,笔记之后会提到),然后从自己的服务器上获取数据,也是因为这一点才有了这篇笔记。

而且小程序中的请求并不是一般前端开发中的 ajax (XMLHTTPRequest 对象),更像是 HTTPS.POST() 或者 HTTPS.GET()

爬虫

最简单的 HTTP 请求

之所以那么简单的就决定写爬虫自己跑一边数据,因为数据位置很明确,数据具体的结构(json)也不复杂,最基本的 HTTP.GET() 就可以满足。以至于计划开始没打算用任何爬虫框架,最后也成功自己手工写了一个基本满足需求的出来。

最简单的 HTTP.GET 封装和请求数据:

修改成为 Promise 形的 interface

出于习惯,也可能是现在前端开发的一般做法,将接口封装成 Promise 形式,上面的封装就演化成如下:

筛选、保存索引

索引(也就是 index.json)的数据中一般格式为 ./json/2017-05-30.daily.json,开头部分 ./json/ 和结尾的 .json 可以去除,只留下 2017-05-30.daily

其次,索引中包含着的不只是「每日精选」,还有「每周精选」。并没有处理每周精选的想法,所以需要有一步进行过滤。过滤完毕之后需要索引的数据全部保存下来,以便之后请求。

通过保存的索引数据请求每天的精选数据

获取完毕索引的数据,经过筛选过滤和简单的处理之后,就是根据「索引」里的那串列表,对每天的「精选」数据进行抓取。

上一步的 Promise 返回了一个数据,这一步可想而知,就是对数组进行循环。不过有两个目标,一个是每一步抓取之后也能够都返回一个 Promise,第二个就是需要有序的执行。而两个需求点又希望可以分装成一个函数,这个函数本身又可以再次返回一个 Promise,以便书写的时候承上启下可以继续 .then(() => doSomething())

在调用的时候,就可以结合第一步中 loadAllURls() 来保持 Promise 链:

但是还没完,经过实测现在饭否精选的数据,仅仅「每日精选」的数据就有六百多条,想一下像以上这样,运行一个函数一口气去抓取六百多条只有一个结果等着着我们,饭否的服务器一脚把我们揣走,close connection。亲测这也是确实的结果,当抓到第四五百条时就没有然后了。

所以在每次发出请求之后还需要留有一定间隔,比如最后我的实现就是一秒去抓一个。因为已经是 Promise 的方式封装,所以定时器的风格也需要统一:

结合到上面的方法中:

每天进行读取保存

即便小程序本身没能上线,但这个爬虫一直在后台(LeanCloud)运行着(出于日后还想针对这个做些什么的心理),每天都在抓取数据(如果有新的产生的话),所以对「索引」需要有个新旧对比的情况,有新的就要去抓取、进行数据保存,没有的话就不浪费流量。 放到爬虫之中,就是每天定时操作抓取上文提到「索引」,之后:

  1. 把新抓取的和已经保存了的数据进行对比,有没有新增;
  2. 有新增的数据,对索引进行保存,把对应日期拿出来,获取对应日期的数据,同时也进行保存;没有新增数据的话,则无需继续操作。

Sample

把上面提到的抽出来做了个简单的 sample,剔除了保存数据到 LeanCloud 和 CornJob 的部分,预览:

两端代码放在 Gist 上,放在同一个文件夹下终端执行 node index.js 就可以了。

感谢阅读

你们好, 2018 年初把小站从 Jekyll 迁移到 Hugo 的过程中,删除了评论区放的 Disqus 插件,考虑有二:首先无论评论、还是对笔记内容的进一步讨论,读者们更喜欢通过邮件、或者 Twitter 私信的方式来沟通;其次一年多以来 Disqus 后台能看到几乎都是垃圾留言(spam),所以这里直接贴一下邮件、以及 Twitter 账户 地址。

技术发展迭代很快,所以这些笔记内容也有类似新闻的时效性,不免有过时、或者错误的地方,欢迎指正 ^_^。

BEST
Lien(A.K.A 胡椒)
本站总访问量 本站总访客量 本文总阅读量