转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/46812645

http://www.llwjy.com/blogdetail/9df464b20cca5405c7ce07e2fb2d768f.html

个人博客站已经上线了,网址 www.llwjy.com
~欢迎各位吐槽~

-------------------------------------------------------------------------------------------------

在前面的几篇博客中,我们已经介绍了怎样採集纵横小说站点上的信息以及怎样把这些信息持久化到数据库中。如今我们就開始介绍怎样做分布式採集,让各个模块之间能够完美的配合。

採集类改动

在開始介绍分布式採集之前。我们须要对之前介绍的採集类加入一些方法。也就是返回上一篇博客中介绍的小说javabean,详细源代码还请參照个人站点上的博客源代码

1.简单介绍页

简单介绍页需呀加入一个方法,让它返回简单介绍页的数据信息,详细例如以下:

	/**
* @return
* @Author:lulei
* @Description: 分析简单介绍页。获取简单介绍页数据
*/
public NovelIntroModel getNovelIntro() {
NovelIntroModel bean = new NovelIntroModel();
bean.setMd5Id(ParseMD5.parseStrToMd5L32(this.pageUrl));
bean.setName(getName());
bean.setAuthor(getAuthor());
bean.setDescription(getDesc());
bean.setType(getType());
bean.setLastChapter(getLatestChapter());
bean.setChapterlisturl(getChapterListUrl());
bean.setWordCount(getWordCount());
bean.setKeyWords(keyWords());
return bean;
}

2.阅读页

阅读页内相同须要加入一个方法。让它返回阅读页内的数据信息,详细例如以下:

	/**
* @return
* @Author:lulei
* @Description: 分析阅读页。获取阅读页数据
*/
public NovelReadModel getNovelRead(){
NovelReadModel novel = new NovelReadModel();
novel.setTitle(getTitle());
novel.setWordCount(getWordCount());
novel.setContent(getContent());
return novel; }

这些方法都是对之前类中的方法做一个整合。将之前分析到的数据组装成一个javabean返回,方便后面的操作。

各页採集线程类

在实现分布式採集的时候,就须要编写各个页面的採集线程类。让他来控制各页面的採集业务。以下我们就一一介绍:

1.更新列表页线程

这个线程的主要功能就是监控更新列表页的数据。提取页面上的简单介绍页URL,觉得它们是有更新的页面,将相应的信息持久化到数据库中,详细实现例如以下:

 /**
*@Description: 更新列表页线程
*/
package com.lulei.crawl.novel.zongheng; import java.util.List;
import java.util.concurrent.TimeUnit; import com.lulei.db.novel.zongheng.ZonghengDb; public class UpdateListThread extends Thread{
private boolean flag = false;
private String url;//抓取的更新列表页URL
private int frequency;//採集频率 public UpdateListThread(String name, String url, int frequency){
super(name);
this.url = url;
this.frequency = frequency;
} @Override
public void run() {
flag = true;
ZonghengDb db = new ZonghengDb();
while (flag){
try {
UpdateList updateList = new UpdateList(url);
List<String> urls = updateList.getPageUrls(true);
db.saveInfoUrls(urls);
TimeUnit.SECONDS.sleep(frequency);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
super.run();
} public static void main(String[] args) {
// TODO Auto-generated method stub
UpdateListThread thread = new UpdateListThread("llist", "http://book.zongheng.com/store/c0/c0/b9/u0/p1/v0/s9/t0/ALL.html", 60);
thread.start(); } }

2.简单介绍页&章节列表页线程类

因为一个简单介绍页就相应一个章节列表页,所以我们就把这两个线程合为一个线程,让事实上现小说简单介绍信息的採集以及小说章节列表信息的採集,详细实现例如以下:

 /**
*@Description: 小说简单介绍信息线程
*/
package com.lulei.crawl.novel.zongheng; import java.util.List;
import java.util.concurrent.TimeUnit; import com.lulei.crawl.novel.zongheng.model.NovelIntroModel;
import com.lulei.db.novel.zongheng.ZonghengDb; public class IntroPageThread extends Thread {
private boolean flag = false; public IntroPageThread(String name) {
super(name);
} @Override
public void run() {
flag = true;
try {
ZonghengDb db = new ZonghengDb();
while (flag) {
//随机获取一个待採集的简单介绍页url
String url = db.getRandIntroPageUrl(1);
if (url != null) {
IntroPage intro = new IntroPage(url);
NovelIntroModel bean = intro.getNovelIntro();
//採集小说章节列表页信息
ChapterPage chapterPage = new ChapterPage(bean.getChapterlisturl());
List<String[]> chapters = chapterPage.getChaptersInfo();
bean.setChapterCount(chapters == null ? 0 : chapters.size());
//更新小说简单介绍信息
db.updateInfo(bean);
//插入待採集的章节列表
db.saveChapters(chapters);
//假设本次有待採集的资源。睡眠一个时间。没有待採集的资源。睡眠还有一个时间
TimeUnit.MILLISECONDS.sleep(500);
}else {
TimeUnit.MILLISECONDS.sleep(1000);
}
}
} catch (Exception e) {
e.printStackTrace();
}
} public static void main(String[] args) {
// TODO Auto-generated method stub
IntroPageThread thread = new IntroPageThread("novelinfo");
thread.start();
} }

3.阅读页线程

这个线程的主要功能就是将小说阅读页的信息採集并持久化到数据库中。详细例如以下:

 /**
*@Description: 小说阅读页线程
*/
package com.lulei.crawl.novel.zongheng; import java.util.concurrent.TimeUnit; import com.lulei.crawl.novel.zongheng.model.NovelChapterModel;
import com.lulei.crawl.novel.zongheng.model.NovelReadModel;
import com.lulei.db.novel.zongheng.ZonghengDb;
import com.lulei.util.ParseMD5; public class ReadPageThread extends Thread {
private boolean flag = false;
public ReadPageThread(String name) {
super(name);
} @Override
public void run() {
flag = true;
ZonghengDb db = new ZonghengDb();
while (flag) {
try {
//随机获取待採集的阅读页
NovelChapterModel chapter = db.getRandReadPageUrl(1);
if (chapter != null) {
ReadPage read = new ReadPage(chapter.getUrl());
NovelReadModel novel = read.getNovelRead();
if (novel == null) {
continue;
}
novel.setChapterId(chapter.getChapterId());
novel.setTime(chapter.getTime());
novel.setUrl(chapter.getUrl());
//保存阅读页信息
db.saveNovelRead(novel);
//将状态改动为不须要採集
db.updateChapterState(ParseMD5.parseStrToMd5L32(novel.getUrl()), 0);
//假设本次有待採集的资源,睡眠一个时间,没有待採集的资源,睡眠还有一个时间
TimeUnit.MILLISECONDS.sleep(500);
} else {
TimeUnit.MILLISECONDS.sleep(1000);
}
} catch(Exception e){
e.printStackTrace();
}
}
} public static void main(String[] args) {
ReadPageThread thread = new ReadPageThread("novel read page");
thread.start();
} }

分布式採集

上面已经介绍完了各个线程完毕的工作,以下就须要一个类来控制管理这些线程。让其执行起来,详细代码例如以下:

 /**
*@Description:
*/
package com.lulei.crawl.novel.zongheng; import java.util.List; import com.lulei.crawl.novel.zongheng.model.CrawlListInfo;
import com.lulei.db.novel.zongheng.ZonghengDb; public class CrawStart {
private static boolean booleanCrawlList = false;
private static boolean booleanCrawlIntro = false;
//简单介绍页採集线程数目
private static int crawlIntroThreadNum = 2;
private static boolean booleanCrawlRead = false;
//阅读页採集线程数目
private static int crawlReadThreadNum = 10; /**
* @Author:lulei
* @Description: 更新列表页採集
*/
public void startCrawlList(){
if (booleanCrawlList) {
return;
}
booleanCrawlList = true;
ZonghengDb db = new ZonghengDb();
List<CrawlListInfo> infos = db.getCrawlListInfos();
if (infos == null) {
return;
}
for (CrawlListInfo info : infos) {
if (info.getUrl() == null || "".equals(info.getUrl())) {
continue;
}
UpdateListThread thread = new UpdateListThread(info.getInfo(), info.getUrl(), info.getFrequency());
thread.start();
}
} /**
* @Author:lulei
* @Description: 小说简单介绍页和章节列表页
*/
public void startCrawlIntro() {
if (booleanCrawlIntro) {
return;
}
booleanCrawlIntro = true;
for (int i = 0; i < crawlIntroThreadNum; i++) {
IntroPageThread thread = new IntroPageThread("novel info thread" + i);
thread.start();
}
} /**
* @Author:lulei
* @Description: 小说阅读页
*/
public void startCrawlRead() {
if (booleanCrawlRead) {
return;
}
booleanCrawlRead = true;
for (int i = 0; i < crawlReadThreadNum; i++) {
ReadPageThread thread = new ReadPageThread("novel read page" + i);
thread.start();
}
} public static void main(String[] args) {
CrawStart start = new CrawStart();
start.startCrawlList();
start.startCrawlIntro();
start.startCrawlRead();
} }

执行结果

通过上面的这几个步骤,纵横小说的分布式採集程序已经完毕,以下就为大家展示一下採集后的数据库截图

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

写在最后

在上面的线程实现中,有非常多的配置信息,比方说线程中的两个请求之间的间隔时间以及各类线程的数量,像这些信息我们都能够将其写到配置文件里,方便之后的改动(这里写到程序中是方便大家的理解,还请见谅)。

----------------------------------------------------------------------------------------------------

ps:近期发现其它站点可能会对博客转载,上面并没有源链接,如想查看很多其它关于 基于lucene的案例开发点击这里。或訪问网址http://blog.csdn.net/xiaojimanman/article/category/2841877
或 http://www.llwjy.com/blogtype/lucene.html

-------------------------------------------------------------------------------------------------

小福利

-------------------------------------------------------------------------------------------------

      个人在极客学院上《Lucene案例开发》课程已经上线了(眼下上线到第二课)。欢迎大家吐槽~

第一课:Lucene概述

第二课:Lucene 经常使用功能介绍

基于lucene的案例开发:纵横小说分布式採集的更多相关文章

  1. 基于lucene的案例开发:查询语句创建PackQuery

    转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/44656141 http://www.llwjy.com/blogdetail/1 ...

  2. 基于zookeeper和强一致性复制实现MySQL分布式数据库集群

    http://qikan.cqvip.com/article/detail.aspx?id=667750898&from=zk_search

  3. 基于AgileEAS.NET企业应用开发平台的分布式解决方案

    开篇 分布式应用 AgileEAS.NET基于Microsoft .Net构件技术而构建,Microsoft .Net最吸引人的莫过于分布式应用技术,基已经提供了XML WebService. .Ne ...

  4. Apache Solr采用Java开发、基于Lucene的全文搜索服务器

    http://docs.spring.io/spring-data/solr/ 首先介绍一下solr: Apache Solr (读音: SOLer) 是一个开源.高性能.采用Java开发.基于Luc ...

  5. 基于JWT的Token开发案例

    代码地址如下:http://www.demodashi.com/demo/12531.html 0.准备工作 0-1运行环境 jdk1.8 maven 一个能支持以上两者的代码编辑器,作者使用的是ID ...

  6. [.NET领域驱动设计实战系列]专题八:DDD案例:网上书店分布式消息队列和分布式缓存的实现

    一.引言 在上一专题中,商家发货和用户确认收货功能引入了消息队列来实现的,引入消息队列的好处可以保证消息的顺序处理,并且具有良好的可扩展性.但是上一专题消息队列是基于内存中队列对象来实现,这样实现有一 ...

  7. 8 个基于 Lucene 的开源搜索引擎推荐

    Lucene是一种功能强大且被广泛使用的搜索引擎,以下列出了8种基于Lucene的搜索引擎,你可以想象它们有多么强大. 1. Apache Solr Solr 是一个高性能,采用Java5开发,基于L ...

  8. WebGIS中兴趣点简单查询、基于Lucene分词查询的设计和实现

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.前言 兴趣点查询是指:输入框中输入地名.人名等查询信息后,地图上可 ...

  9. Lucene/Solr搜索引擎开发笔记 - 第1章 Solr安装与部署(Jetty篇)

    一.为何开博客写<Lucene/Solr搜索引擎开发笔记> 本人毕业于2011年,2011-2014的三年时间里,在深圳前50强企业工作,从事工业控制领域的机器视觉方向,主要使用语言为C/ ...

随机推荐

  1. 使用spring mvc或者resteasy构建restful服务

    看到最近一个项目里用resteasy来构建restful接口,有点不明白,不少Spring mvc4.0以后也可以很方面的实现restful服务吗,为啥还要在Spring MVC的项目里还引入rest ...

  2. VUEJS2.0源码理解--优

    VUEJS2.0源码理解 http://jiongks.name/blog/vue-code-review/#pingback-112428

  3. 配置Windows群集

    故障转移群集 l  一个群集支持8个节点,(64位操作系统支持16个节点) l  可以使用故障转移群集的服务:SQL Server(数据库), Exchange(邮件),文件和打印服务,DHCP服务等 ...

  4. POJ3087 Shuffle'm Up

    题目: 现有字符串s1.s2.s12,其中s1.s2的长度为len,s12的长度为2*len. 是否可以通过一些操作使s1和s2转换合并成s12? 变换的操作规则如下: 假设s1=11111,s2=0 ...

  5. 第4章 部署模式 Three-Tiered Distribution(三级分布)

    影响因素 Tiered Distribution 中讨论的影响因素也适用于此模式.有关这些通用影响因素的讨论,请参阅"Tiered Distribution".下列影响因素仅适用于 ...

  6. css中max-width和min-width的应用

    max-width:从字面意思可以看出,是规定元素本身最大宽度,元素本身宽度应小于等于最大宽度值. min-width:从字面意思可以看出,是规定元素本身最小宽度,元素本身宽度应大于等于最小宽度值. ...

  7. [ Database ] [ SQL Server ] SQL Server 很多不允許的操作解決方法

    說明可參考 https://blog.miniasp.com/post/2012/10/26/SQL-Server-Management-Studio-Prevent-saving-changes-t ...

  8. 【Oracle】修改参数的同时添加注释

    当修改参数时添加注释,我们会用到如下语句: alter system set parameter=value comment='description'; --修改参数需要有相应权限的用户去执行. 例 ...

  9. C++序列化使用

    error C2248 无法访问私有成员 :原因 ifstream 作为参数必须传引用! (1):C++使用STL序列化:原文链接:http://blog.csdn.net/pandaxcl/arti ...

  10. Javascript阻止表单提交

    Javascript阻止表单提交 Html 1.<form name="loginForm" action="login.aspx" method=&qu ...