使用Kotlin Coroutines简单改造原有的爬虫框架

NetDiscover 是一款基于 Vert.x、RxJava2 实现的爬虫框架。因为我最近正好在学习 Kotlin 的 Coroutines,在学习过程中尝试改造一下自己的爬虫框架。所以,我为它新添加了一个模块:coroutines 模块。

一. 爬虫框架的基本原理:

对于单个爬虫而言,从消息队列 queue 中获取 request,然后通过下载器 downloader 完成网络请求并获得 html 的内容,通过解析器 parser 解析 html 的内容,然后由多个 pipeline 按照顺序执行操作。其中,downloader、queue、parser、pipeline 这些组件都是接口,爬虫框架里内置了它们很多实现。开发者可以根据自身情况来选择使用或者自己开发全新的实现。

下面响应式风格的代码反映了上图爬虫框架的基本原理:

其中,Downloader的download方法会返回一个Maybe。

正是因为这个 Maybe对象,后续的一系列的链式调用才显得非常自然。比如将Response转换成Page对象,再对Page对象进行解析,Page解析完毕之后做一系列的pipeline操作。

当然,在爬虫框架里还有 SpiderEngine 可以管理 Spider。

二. 使用协程改造

协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。

由于 Kotlin Coroutines 仍然是试验的API,所以我不打算在爬虫框架原有的 core 模块上进行改动。于是,新增一个模块。

在新模块里,将之前的响应式风格的代码,改造成协程的方式。

Kotlin Coroutines 为各种基于 reactive streams 规范的库提供了工具类。可以在下面的github地址找到。

https://github.com/Kotlin/kotlinx.coroutines/tree/master/reactive

我在build.gradle中添加了

注意,协程的版本号必须跟 Kotlin 的版本要相符和。我所使用的 Kotlin 的版本是1.2.41

下面是修改之后的 Kotlin 代码,原有的各种组件接口依然可以使用。

其中,download 变量返回了 Maybe的结果。之后, run、apply 等 Kotlin 标准库的扩展函数替代了原先的 RxJava 的 map 操作。

Kotlin 的协程是无阻塞的异步编程方式。上面看似同步的代码,其实是异步实现的。

await() 方法是 Maybe 的扩展函数:

由于 await() 方法是 修饰的,所以在上述代码的最外层还得加上一段代码,来创建协程。

到此,完成了最初的改造,感兴趣的同学可以查看我的爬虫框架。github地址:https://github.com/fengzhizi715/NetDiscovery

三. 小结

随着 Kotlin Coroutines 未来的正式发布,爬虫框架的 coroutines 模块也会考虑合并到 core 模块中。以及随着个人对 Kotlin Coroutines 的进一步认识和理解,也会考虑在更多的地方使用 Coroutines ,例如 Vert.x 和 Kotlin Coroutines 相结合。

关注【Java与Android技术栈】

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180809G0BCM800?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券