因为毕业设计选了爬虫。而之前又没怎么接触过爬虫,只能从爬虫入门视频开始看,一点点学习摸索,所以前前后后写了将近两个月。今天可算是大致完工了,接下来就随便写写这个毕设的过程吧,记录一下。我太难了,也太菜了,唉。
不得不说,java的爬虫是真的少。虽然b站能搜到大约四五个完整的java爬虫教学视频。但是这些视频也仅仅够入门,都是只讲了基础的网页下载、解析、多线程爬取等等内容。爬取的网站也大多是十分简单的静态页面。
而像现在已经使用非常广泛的动态网页加载技术,几乎找不到对应的教学视频。只能自己搜各种博客看。而没有一个系统的教学框架,仅仅看博客是真的费劲。
至于说主题爬虫的相关算法,更是没有对应的教学视频了。只能一点点在网上找博客看,从知网上大量下载相关的论文去研究。
最终这个简单的毕设算是写出来了,个人感觉勉勉强强能应付得了毕设(其实心里还是没什么底,但是如果老师给面子的话应该不至于过不去)。
最开始学的时候,用的是URLConnection+正则表达式+java自带的数据结构(如HashSet)的模式,写出一个最简单的单线程,针对静态网页循环抓取的爬虫;再到HttpClient+HtmlParser(随后又改为jsoup)+布隆过滤器(仍然是单线程);再到HttpClient+jsoup+内存数据库(多线程);再到HtmlUnit+jsoup+布隆过滤器(内存数据库用着太麻烦了,直接持久化了个布隆过滤器。。。);但是这个时候发现HtmlUnit是真的不好用,也许是我太菜了,但是同样的js代码,用WebDriver就可以执行并获取到完整的网页,用HtmlUnit就不行,最终我放弃了HtmlUnit。
所以项目最终的结构是:Selenium+jsoup+布隆过滤器的模式,一个管下载,一个管解析,布隆过滤器管已访问url,我还用了java自带的PriorityQueue来做TODOLIST,同样是持久化到本地。
既然是主题爬虫,那肯定要有主题计算,主题计算部分用的算法分别是:Fish-Search算法(计算当前页面相关度),Shark-Search算法(预测子链接相关度)。分词工具用的是结巴分词。
整个爬虫的流程就是:种子URL-->下载页面-->计算页面相关度-->解析页面,获取子链接(如果是文章页面,就获取正文内容并存入本地形成文档集)-->预测子链接相关度-->大于设定阈值则加入TODOLIST,否则丢弃(没使用算法的爬行策略,这对我来说太难了)-->一轮爬取结束。
然后就是等待爬虫爬到足够多的数据,开始下一步,创建倒排索引。
创建倒排索引简单来讲就是将所有文档进行分词,形成一个包含所有单词的集合,然后去掉重复的单词,把这些单词存到一个Map<String,List<File>>集合中,key就是单词,value是单词对应的文档集合,比如说单词“java”在文档1,文档2,文档5中都存在,那么对应的记录就是 java-->{文档1,文档2,文档5}。
创建完倒排索引,把它持久化到本地,形成一个倒排索引文件,这样下次就不需要再重新创建了,毕竟创建倒排索引是个很耗费时间的过程。
然后就是搜索了,用户输入查询的语句,然后使用分词工具将用户输入进行分词,去掉停用词。然后看看倒排索引里哪些文档包含这些分词后形成的单词,再用TF-IDF算法计算每篇文档的相关性得分,然后排序,把排完序的集合返回,用JSP展示一下就OK了。
大致效果如下图:
点击链接会跳转到对应的原文网页,如下图:
睡了睡了。以后再多学习学习爬虫的技术,自己还是太菜了,写的东西bug又多,功能又简单。唉