优雅的使用WebMagic框架,爬取唐诗别苑网的诗人诗歌数据html
同时在几种动态加载技术(HtmlUnit、PhantomJS、Selenium、JavaScriptEngine)中对比做选择jquery
WebMagic虽然差很少两年没有维护,但其自己是一个优秀的爬虫框架的实现,源码中有不少值得参考的地方,特别是对爬虫多线程的控制。另外,因为页面爬取到的是非结构化数据,因此数据保存到MongoDB。
涉及技术:git
pom.xml文件中的依赖很是简单,并无使用到Spring系列的框架,因此有些地方本身编码实现了Spring提供的功能
根据需求将数据保存到MongoDB数据库,所以在程序运行前必须设置好resources/mongodb.properties
文件github
最好保证MongoDB的版本是4.0以上。另外MongoDB的用户管理比较麻烦,过程大体以下:首先须要建立存储数据的数据库,如命名为user_tangpoem,并存入随便一条数据(集合)使数据库有效化,而后建立一个
admin数据库的root用户,继续建立一个能够读写应用数据库user_tangpoem的用户,而后修改MongoDB配置文件使其以安全认证模式启动。重启数据库,选择admin数据库(use admin)
用刚刚建立的用户(非root用户)使用db.auth()进行登陆,返回1说明验证成功,选择user_tangpoem数据库(use user_tangpoem),输入show collections,若是看到最初建立数据库时的集合,则说明用户建立成功。
详细可参考 MongoDB4.0.0 远程链接及用户名密码认证登录配置——windows
爬虫以多线程的方式运行,在resources/spider.properties
文件中能够设置线程数和线程睡眠时间,在设置好数据库配置的基础上,直接运行Main.main(),爬虫就会开始爬取。web
线程睡眠,是WebMagic框架源码中每线程爬取完一个url后必然经历的过程,但做者文档并无对此进行说明,请根据实际状况调整
WebMagic底层已经很好的使用了HttpClient加载静态页面,对于动态页面,也有PhantomJSDownloader和SeleniumDownloader两个经常使用的利用
浏览器内核模拟浏览器行为的实现,其中,PhantomJS须要指定phantomjs.exe和进行爬取的JS文件,而seleniumDownloader须要指定chromedriver.exe,须要自行下载对应操做系统的版本,
使用起来并不难,本项目很少做讨论。这里关键说明HtmlUnitmongodb
一款开源的Java页面分析工具,读取页面后,能够有效的使用HtmlUnit分析页面上的内容。使用纯Java实现的模拟浏览器,不须要指定外部文件。chrome
虽然其对JS的支持并不彻底,但整体而言HtmlUnit的内存消耗、CPU消耗和效率都比PhantomJS和Selenium好,值得进行使用数据库
本项目使用2.25版本的HtmlUnit并无出现JS加在不成功的问题,但使用2.3x的版本会没法加载
由于JavaScriptEngine是有局限性的,最明显就是其不支持jquery的语法,由于jquery使用了浏览器内置的对象,而JS引擎自己是没有浏览器对象的windows
固然能够,只要分析过页面的加载逻辑,若是不涉及浏览器对象的使用,或者将JS逻辑进行转化,仍是可以使用JS引擎的,但牺牲了泛用性。本项目经分析后使用JS引擎加载浏览器
通过测试,三者比较以下
PhantomJS使用外置的程序,因此JVM没法管理这部分的硬件资源,须要打开任务管理器
通过分析,爬取步骤分为4步:
显然,如上描述,采用的是宽度优先遍历,因此当执行到第3步时,才会有数据入库优化后使用Java8的nashorn JS引擎执行JS代码,不须要动态加载JS,因此不会出现4的问题
根据爬取过程分析,忽略程序启动时间和调用获取诗人id接口的时间
在开启8线程的并发模式下(使用HtmlUnit进行动态加载):
一共须要: 2529 / 8 5 + 48000 (1 + 0.01)/ 8 * 10 ≈ 62596秒 ≈ 1043分钟 ≈ 17.4小时
上述数据是在本地测试中获得的,配置为 win10 8G i5-4210M 4核
优化后,用JS引擎取代模拟浏览器动态加载JS,获取诗歌信息的耗时明显缩短,由10秒缩短到6秒左右,所以从新计算耗时以下:
2529 / 8 5 + 48000 / 8 6 ≈ 37185秒 ≈ 620分钟 ≈ 10.3小时
当使用模拟浏览器动态加载JS时,观察JVM的使用状况,发现爬取诗歌阶段频繁发生Minor GC(新生代GC),差很少10秒一次,以下图所示,
后判明是多线程模拟浏览器加载页面行为很是的耗内存(参考同时打开8个浏览器加载网页),对象频繁建立,频繁消耗,
建议运行时经过-Xms -Xmx把JVM内存设置得大些,至少1G,而后把新生代的比例设大,如-Xms2048M -Xmx2048M -XX:+UseParallelOldGC -XX:NewRatio=1
后来,用JS引擎取代模拟浏览器动态加载JS,不只速度获得明显提高,并且内存的消耗大幅度下降,Minor GC平均1分钟发生一次,以下图所示,
最后附上GitHub项目地址:https://github.com/Kanarienvogels/spider-tangpoem