使用BDB来存储已爬地址,用int status的各个不同的位,来表示不同的访问状态:
访问过;保存过;修改过 等等
package com.rayeen.spider.vertical.data;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.apache.hadoop.io.MD5Hash;
import org.apache.log4j.Logger;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;
import com.sleepycat.persist.EntityStore;
import com.sleepycat.persist.PrimaryIndex;
import com.sleepycat.persist.SecondaryIndex;
import com.rayeen.spider.vertical.constant.MetResourceTag;
import com.rayeen.spider.vertical.constant.MsgConstant;
import com.rayeen.spider.vertical.util.ResutTree;
import org.apache.commons.lang.*;
public class MetResourceProtocolImpl implements MetResourceProtocol {
public MetResourceProtocolImpl(String name){
this.name=name;
}
String name;
static final Logger LOG = Logger.getLogger(ResutTree.class);
public static String openMode = "append";
public static int hitCnt = 0;
private static MyDbEnv myDbEnv = new MyDbEnv();
static EntityStore da;
static PrimaryIndex<String, MetResourceBE> infoMap = null;
static SecondaryIndex<String, String, MetResourceBE> infoMapByDigest = null;
static int flushCnt = 0;
//初始化BDB数据库环境
public synchronized void initilize() throws DatabaseException {
Environment myDbEnvironment = null;
File met = new File("./metResource");
if(!met.exists()){
met.mkdir();
}
File file = new File("./metResource/"+name);
try {
if (!file.exists()) {
if (!file.exists()) {
file.mkdir();
}
myDbEnv.close();
myDbEnv.setupNoTransact(file, false);
} else {//
try {
myDbEnv.setupAppend(file);
} catch (Exception e) {
LOG.error(e.getMessage());
file.delete();
file.mkdir();
myDbEnv.setupNoTransact(file, false);
}
}
myDbEnv.setCacheSize(1024);
} catch (DatabaseException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
da = myDbEnv.getEntityStore();
infoMap = da.getPrimaryIndex(String.class, MetResourceBE.class);
infoMapByDigest = da.getSecondaryIndex(infoMap, String.class,
"digest");
} catch (DatabaseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public int error() throws IOException {
throw new IOException("bobo");
}
public int getMetResource(String uri, byte[] content) {
if(null==uri) return 0;
LOG.info("uri:" + uri);
try {
MetResourceBE metResource = infoMap.get(uri);
if (metResource != null) {
int status = metResource.getStatus();
String hash = "";
if (content == null) {
hash = MD5Hash.digest(uri).toString();
} else {
hash = MD5Hash.digest(content).toString();
}
int oldStatus = 0;
String oldHash = metResource.getDigest();
if (StringUtils.equalsIgnoreCase(oldHash, hash)) {
status ^= MetResourceBE.MODIFIED;// 去掉“修改过”标志位,未更改过
status |= MetResourceBE.UNMODIFIED;// 去掉“修改过”标志位,未更改过
} else {
status ^= MetResourceBE.UNMODIFIED;//未更改过
status |= MetResourceBE.MODIFIED;// 更改过
}
LOG.info("status:" + status);
return status;
}
} catch (DatabaseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return 0;
}
/**
*
* @param uri
* 地址
* @param content
* 内容
* @param status
* 当前状态(“经过但是不保存”还是“保存”)
* @return
* @throws DatabaseException
*/
public String putMetResource(String uri, byte[] content, int status,
MetResourceTag type) throws DatabaseException {
String hash = "";
//uri = uri.toLowerCase();
if (content == null) {
hash = MD5Hash.digest(uri).toString();
} else {
hash = MD5Hash.digest(content).toString();
}
MetResourceBE metResource = null;
//覆盖
if (type == MetResourceTag.COVER) {
metResource = infoMap.get(uri);
metResource = new MetResourceBE();
metResource.setUri(uri);
metResource.setDigest(hash);
metResource.setStatus(status);
infoMap.putNoReturn(metResource);
myDbEnv.sync();
return MsgConstant.SUCCESS;
}
int oldStatus = 0;
if (infoMap.contains(uri)) {
metResource = infoMap.get(uri);
oldStatus = metResource.getStatus();
String oldHash = metResource.getDigest();
if (StringUtils.equalsIgnoreCase(oldHash, hash)) {
oldStatus ^= MetResourceBE.MODIFIED;// 去掉“修改过”标志位,未更改过
oldStatus |= MetResourceBE.UNMODIFIED;// 去掉“修改过”标志位,未更改过
} else {
oldStatus ^= MetResourceBE.UNMODIFIED;// 去掉“未修改过”标志位,未更改过
oldStatus |= MetResourceBE.MODIFIED;// 更改过
}
oldStatus |= status;
metResource.setStatus(oldStatus);
} else {// 遇到过相同的页面
if (infoMapByDigest.contains(hash)) {
oldStatus = MetResourceBE.SAME_CONTENT;// 不同uri相同页面
} else {// 没有遇到过相同内容的页面
// 根据status来设置是met还是saved
oldStatus = status;
}
metResource = new MetResourceBE();
metResource.setUri(uri);
metResource.setDigest(hash);
metResource.setStatus(oldStatus);
}
if (null != metResource) {
infoMap.putNoReturn(metResource);
if(flushCnt++ % 5==0){
myDbEnv.sync();
}
}
return MsgConstant.SUCCESS;
}
public int getMetResource(String uri) {
// TODO Auto-generated method stub
return getMetResource(uri, null);
}
/**
* type: 覆盖还是融合
*/
public String putMetResource(String uri, String content, int status,
MetResourceTag type) throws DatabaseException {
try {
putMetResource(uri, content.getBytes("UTF-8"), status, type);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (DatabaseException e) {
e.printStackTrace();
}
if(flushCnt++ % 5==0){
myDbEnv.sync();
}
return MsgConstant.SUCCESS;
}
}
其中MetResourceBE的实现:
package com.rayeen.spider.vertical.data;
import java.io.Serializable;
import java.util.logging.Logger;
import com.sleepycat.persist.*;
import com.sleepycat.persist.model.*;
import com.sleepycat.persist.model.Entity;
import com.sleepycat.persist.model.PrimaryKey;
import com.sleepycat.persist.model.SecondaryKey;
import com.sleepycat.persist.model.Relationship;
@Entity
public class MetResourceBE implements Serializable{
@PrimaryKey(sequence="ID")
private String uri;
@SecondaryKey(relate=Relationship.MANY_TO_ONE)
private String digest;
private java.util.Date insertTime;
private int status;
final static public int MET=0x1;//url遇到过
final static public int SAVED=0x2;//url保存过
final static public int MODIFIED=0x4;//内容更新过
final static public int UNMET=0x8;//url未遇到过
final static public int UNSAVED=0x10;//url未保存过
final static public int UNMODIFIED=0x20;//内容未更新
final static public int BLANK=0x0;//未遇到过,未保存过,未更新过
final static public int FULL=MET|SAVED|MODIFIED|UNMET|UNSAVED|UNMODIFIED;// 遇到过, 保存过, 更新过
//
//final static public int MET_MODIFIED=0x5;//遇到url相同,内容不同的页面
// final static public int UNMET=0x0;//url遇到过,未更新过,未保存过
// final static public int UNSAVED_UNMODIFY=0x4;//遇到过,更新或未更新过,未保存过
// final static public int UNSAVED_MODIFY=0x6;//遇到过,更新或未更新过,未保存过
//final static public int UNSAVED=0x8;//url保存过
final static public int SAME_CONTENT=0x10;//遇到url不同,内容相同的页面
final static public int SAME_URL=0x20;//遇到url相同,内容不同的页面
// final static public int MODIFIED=0x40;//遇到url相同,内容不同的页面
// final static public int UNMODIFIED=0x80;//遇到url相同,内容不同的页面
public java.util.Date getInsertTime() {
return insertTime;
}
public void setInsertTime(java.util.Date insertTime) {
this.insertTime = insertTime;
}
public String getDigest() {
return digest;
}
public void setDigest(String digest) {
this.digest = digest;
}
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
判断是否爬过某个页面的代码片段:
// 在fetchedList非空的情况下才处理以下逻辑
if (null != fetchedList) {
int curStatus = fetchedList.getMetResource(realUrl, content
.getBytes("UTF-8"));
// 如果不应该处理这个页面,那么直接返回
if (ParseUtils.EntranceCantProcess(processStandard, curStatus)) {
log(MetResourceUtil.explainMetResourceReason(
url.getToUrl(), processStandard, curStatus),
LogType.ENTRANCE_CONDITIONAL);
return curStatus;
}
// 否则,记录这个页面的状态(met和unmet状态转换)
fetchedList.putMetResource(url.getToUrl(), content
.getBytes("UTF-8"), MetResourceBE.UNMET
| MetResourceBE.MET, MetResourceTag.MERGE);
}
保存数据之后,修改URL状态的代码片段:
public void save(String saveStat) throws SemanticException {
// curHierarchyResultMap中保存着到上级页面为止的入口处的信息
// 之前的若干步骤都是为了填充curHierarchyResultMap里的数据
// 这里的curHierarchyResultMap是上层的crawl函数设进参数的HierarchyResultMap
// 本层的所有save函数共用这个curHierarchyResultMap
// curUri会被enter之后的处理过程还原出来,强行设置为
VMUtils.save(curUri, curPage, curHierarchyResultMap, curCrsc, saveStat);
// 保存“已保存过标记”
if (null != fetchedList) {
try {
fetchedList.putMetResource(curUrl.getToUrl(), curContent,
MetResourceBE.SAVED | MetResourceBE.UNSAVED,
MetResourceTag.MERGE);
} catch (DatabaseException e) {
e.printStackTrace();
}
}
}
一些位操作的辅助函数:
static TObjectIntHashMap bitmap = new TObjectIntHashMap();
static {
bitmap.put("遇到过", MetResourceBE.MET);
bitmap.put("更新过", MetResourceBE.MODIFIED);
bitmap.put("保存过", MetResourceBE.SAVED);
bitmap.put("未遇到过", MetResourceBE.UNMET);
bitmap.put("未更新过", MetResourceBE.UNMODIFIED);
bitmap.put("未保存过", MetResourceBE.UNSAVED);
}
/**
* 处理前三位数据 111(未遇到过||更新过||未保存过)& 001(未保存过) 返回前3位数据(位置上的后三位,逻辑上的前3位)
*
* @param standard
* @return
* @throws SemanticException
*/
public static int parseProcessStardard(String standard)
throws SemanticException {
if (null == standard)
return -1;
int idx = standard.indexOf(ConfConstant.PROCESS_STANDARD);
int status = 0;
if (idx != -1) {
standard = standard.substring(idx
+ ConfConstant.PROCESS_STANDARD.length() + 1);
}
String[] stdsOR = Pattern.compile("||", Pattern.LITERAL).split(
standard, 0);
int or = MetResourceBE.BLANK;
for (String strOR : stdsOR) {
strOR = strOR.trim();
int and = MetResourceBE.BLANK;
String[] stdsAND = Pattern.compile("&&", Pattern.LITERAL).split(
strOR, 0);
for (String strAnd : stdsAND) {
strAnd = strAnd.trim();
if (!bitmap.containsKey(strAnd)) {
ParalleIRVirtualMachine.error(
"error enterance strandard grammer:"
+ strAnd.substring(1), ErrorType.GRAMMER);
}
and |= bitmap.get(strAnd);
}
or = or | and;
}
status = or;
return status;
}
static public boolean canProceess(int standard, int status) {
return ((standard | status) & MetResourceBE.FULL) > 0;
}
static public boolean PageCanProceess(String standardStr, int status)
throws SemanticException {
int standard = parseProcessStardard(standardStr);
return ((standard | status) & MetResourceBE.FULL) > 0;
}
// 如果:所有遇到过的uri都不进入(不探测是否更新),则在met的情况下,cantEnter返回true
static public boolean EntranceCantEnter(String standardStr, int status)
throws SemanticException {
int standard = parseProcessStardard(standardStr);
return EntranceCantEnter(standard, status);
}
static public boolean EntranceCantEnter(int standard, int status) {
if (standard == -1)
return false;
// url遇到过,未更新过,未保存过
if (standard == MetResourceBE.UNMET && (status & MetResourceBE.MET) > 0) {
return true;
}
// 未保存过+更新过+遇到过+<->当前状态:未保存过+未更新过+遇到过+
//
return false;
}
// 如果标准是:更新过,而status是未更新过
// 或者标准是:未保存过,而status是保存过,那么,本页不需要处理
// 如果标准是:更新过,未保存过,status是未更新过,未保存过,那么,没有不能完全符合,也不能处理
// 不考虑是否遇到过这个页面
// 只处理标准中提到的信息,没提到的无所谓
// 是否需要多加一倍的字段数? 由3位01变成6位01?
static public boolean EntranceCantProcess(int standard, int status) {
if (standard == -1)
return false;
// "未遇到过"也就是,status中的"未遇到过"位必须是1
if ((standard & MetResourceBE.UNMET) > 0
&& (status & MetResourceBE.UNMET) > 0) {
return true;
}
// 是否更新过
if (((standard & MetResourceBE.MODIFIED) ^ (status & MetResourceBE.MODIFIED)) != 0) {
return true;
}
// 如果标准是:更新过||未保存过||未遇到过 , 而status是未更新过&&未保存过&&遇到过,
// 则不处理这个页面
if (standard == (MetResourceBE.MODIFIED | MetResourceBE.SAVED | MetResourceBE.MET)
&& status == (MetResourceBE.MODIFIED | MetResourceBE.SAVED)) {
return true;
}
return false;
}
分享到:
相关推荐
《基于IRVM的锂电池荷电状态评估方法与仿真验证》 在电动汽车领域,锂电池的荷电状态(SOC)是至关重要的参数,它直接影响到电池的性能和寿命。由于SOC无法直接测量,需要依赖于电池电压、充放电电流和温度等物理量...
IRVM可能是这个网站提供的一个在线工具,用于查看、分析或执行编译器生成的IR代码。 标签 "1" 可能代表实验的级别或者序列,暗示这是一系列实验中的第三个,或者它可能指代实验的某种分类,但具体含义需要更多上...
基于springboot大学生就业信息管理系统源码数据库文档.zip
基于java的驾校收支管理可视化平台的开题报告
时间序列 原木 间隔5秒钟 20241120
毕业设计&课设_基于 Vue 的电影在线预订与管理系统:后台 Java(SSM)代码,为毕业设计项目.zip
基于springboot课件通中小学教学课件共享平台源码数据库文档.zip
基于java的网上购物商城的开题报告
Delphi人脸检测与识别Demo1fdef-main.zip
基于java的咖啡在线销售系统的开题报告
基于java的自助医疗服务系统的开题报告.docx
内容概要:本文档全面介绍了Visual Basic(VB)编程语言的基础知识和高级应用。首先概述了VB的基本特性和开发环境,随后详细讲述了VB的数据类型、变量、运算符、控制结构、数组、过程与函数、变量作用域等内容。接着介绍了窗体设计、控件使用、菜单与工具栏的设计,文件操作、数据库访问等关键知识点。最后讨论了VB的学习方法、发展历史及其在桌面应用、Web应用、数据库应用、游戏开发和自动化脚本编写等领域的广泛应用前景。 适合人群:初学者和中级程序员,尤其是希望快速掌握Windows桌面应用开发的人群。 使用场景及目标:①掌握VB的基础语法和开发环境;②学会使用VB创建复杂的用户界面和功能完整的应用程序;③理解数据库操作、文件管理和网络编程等高级主题。 其他说明:Visual Basic是一种简单易学且功能强大的编程语言,尤其适合用于开发Windows桌面应用。文中不仅覆盖了基础知识,还包括了大量的实用案例和技术细节,帮助读者快速提升编程技能。
基于java的疫情期间高校防控系统开题报告.docx
基于springboot+vue社区老年人帮扶系统源码数据库文档.zip
基于java的超市商品管理系统的开题报告.docx
基于SpringBoot房屋买卖平台源码数据库文档.zip
xdu限通院23微处理器系统与应用大作业(两只老虎),适应于汇编语言keil软件,
<项目介绍> - 新闻类网站系统,基于SSM(Spring、Spring MVC、MyBatis)+MySQL开发,高分成品毕业设计,附带往届论文 - 不懂运行,下载完可以私聊问,可远程教学 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 --------
基于java的学生网上请假系统的开题报告.docx
社会经济繁荣发展的今天,电子商务得到了飞速发展,网上交易越来越彰显出其独特的优越性,在人们的日常生活中,出现了各种类型的交易网站。其中一个就是车辆易主交易网站,它是一个服务于用户买卖二手车辆的交易网站,为用户提供了平等互利、方便快捷的网上交易平台,通过这一类型的网站,用户可自由出售和购买车辆。 本课题主要根据车辆本身的特性,充分发挥互联网的特点与优势,构建一个以二手车辆为商品、基于互联网平台的车辆易主业务交易管理系统,并根据车辆易主业务交易管理系统的应用需求,进行需求分析,进而对网站系统作规划设计。采用IDEA为运行平台,以SSH为框架,运用HTML语言、JSP技术、MySql数据库、JSP与后台数据库链接等关键技术建设二手车网上交易系统,构建车辆易主交易系统的会员注册与登录,网站首页展示、用户发布商品车辆,用户求购商品车辆,分页浏览、购物系统、用户后台管理、管理员用户后台管理等功能,并使这些功能得以实现并更好为用户服务。网站整体构建完成且测试成功后,用户可以进入网站进行注册、登录,登录后,用户可以在网站上发布自己的闲置车辆或者寻找想要购买的车辆,还可以收藏车辆,管理发布和收藏的车辆,