使用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" 可能代表实验的级别或者序列,暗示这是一系列实验中的第三个,或者它可能指代实验的某种分类,但具体含义需要更多上...
光伏风电混合并网系统Simulink仿真模型:光伏发电与风力发电的协同控制与并网逆变器设计,光伏风电混合并网系统simulink仿真模型。 系统有光伏发电系统、风力发电系统、负载、逆变器lcl大电网构成。 光伏系统采用扰动观察法实现mppt控制,经过boost电路并入母线; 风机采用最佳叶尖速比实现mppt控制,通过三相电压型pwm变器整流并入母线; 并网逆变器VSR采用基于电网电压定向矢量控制双闭环,经过lcl滤波器并入大电网。 ,核心关键词: 1. 光伏风电混合并网系统 2. Simulink仿真模型 3. 光伏发电系统 4. 风力发电系统 5. 负载 6. 逆变器LCL大电网 7. MPPT控制 8. 扰动观察法 9. Boost电路 10. 最佳叶尖速比 11. 三相电压型PWM变换器 12. VSR电网电压定向矢量控制双闭环 13. LCL滤波器 以上关键词用分号分隔为: 光伏风电混合并网系统;Simulink仿真模型;光伏发电系统;风力发电系统;负载;逆变器LCL大电网;MPPT控制;扰动观察法;Boost电路;最佳叶尖速比
DXP元器件库,初学者有用
2025专业技术人员继续教育公需课题库(附含答案).pptx
C++编写的资产管理系统(带SQLServer数据库文件。)。
Simulink下的MATLAB平台在智能电网微网运行控制中的并网仿真与逆变器控制策略探讨,Simulink:智能电网微网运行控制仿真及其参考资料 关键词:微电网 运行控制 仿真平台:MATLAB 主要内容:并网仿真 逆变器控制 下垂控制 ,关键词:微电网; 运行控制; Simulink仿真; MATLAB; 并网仿真; 逆变器控制; 下垂控制; 智能电网微网。,"Simulink在MATLAB平台下的微电网运行控制仿真研究及资料整合"
Matlab中的HMM隐马尔科夫与Markov马尔科夫时间序列预测源代码及数据集(可运行,适用于单变量预测),HMM隐马尔科夫时间序列预测 Markov马尔科夫时间序列预测(Matlab) 1.所有程序经过验证,保证可以运行 2.程序包括源码(主程序一个,子函数两个)和数据集; 3.程序适用于单变量时间序列预测。 注意:HMMP为主程序、data为数据集,其余m文件为函数文件,运行主文件HMMP即可。 ,HMM隐马尔科夫模型; 时间序列预测; Matlab程序; 验证可用; 主程序; 函数文件; 单变量预测; 包含源码与数据集。,"HMM与马尔科夫模型结合的时间序列预测程序(Matlab)验证版"
项目已获导师指导并通过的高分毕业设计项目,可作为课程设计和期末大作业,下载即用无需修改,项目完整确保可以运行。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行!可以放心下载 技术组成 语言:java 开发环境:idea 数据库:MySql8.0 部署环境:Tomcat(建议用 7.x 或者 8.x 版本),maven 数据库工具:navicat
python学习练习游戏案例,详细备注解释代码,最适合初学者,练手学习,资源已上传欢迎下载学习
三菱FX系列自由口通讯程序详解:FX3U-232BD与上位机通讯及PLC与触摸屏应用,三菱FX自由口通讯程序 三菱FX系列自由口通讯程序 利用FX3U-232BD与上位机自由口通讯, 有PLC程序和触摸屏程序,通过连接三根线即可通讯 具有很好的学习意义和借鉴价值。 ,核心关键词:三菱FX系列; 自由口通讯程序; FX3U-232BD; 上位机; PLC程序; 触摸屏程序; 三线连接; 学习意义; 借鉴价值。,三菱FX系列自由口通讯程序:简易编程与实用连接指南
1990-2022年各省份基尼系数
Python自动化办公源码-60 pandas-matplotlib
MATLAB下的模型预测控制在楼宇负荷需求响应中的研究与应用:结合热力学与舒适度考量,MATLAB代码:基于模型预测控制的楼宇负荷需求响应研究 关键词:楼宇负荷 空调 模型预测控制 需求响应 参考文档:《Model Predictive Control of Thermal Storage for Demand Response》完全复现 仿真平台:MATLAB+CVX平台 主要内容:代码主要做的是一个建筑楼宇的需求响应问题,首先利用楼宇的储热特性,结合热力学方程构建了其储热模型,其次,考虑在动态能量电价的引导下,对楼宇负荷进行需求侧管理,从而能够对其负荷曲线进行改善,在需求响应的过程中也考虑了用户的舒适度,相对来讲比较全面,模型的求解采用的是较为创新的模型预测控制算法,更加创新,而且求解的效果更好,店主已经对代码进行了深入的加工和处理,出图效果非常好,代码质量非常高 ,关键词:楼宇负荷; 空调; 模型预测控制; 需求响应; 储热模型; 动态能量电价; 舒适度; MATLAB代码; CVX平台; 深入处理。,基于MATLAB的模型预测控制研究:楼宇负荷需求响应管理与优化
Prius 2004永磁同步电机设计报告:从理论到实践——磁路法、Maxwell仿真建模与温升分析,Prius2004永磁同步电机设计报告: 磁路法、maxwell有限元法、MotorCAD温仿真、应力分析。 (内容比较完善,用于很需要的朋友,不支持讲解,等额外服务哈。 ) 内容:: 1.Excell设计程序,可以了解这个电机是怎么设计出来的,已知功率转矩等,计算电机的体积,叠厚,匝数等。 2.Maxwell参数化仿真模型:可以学习参数化仿真模型,有限元结果可查看。 3. 橡树岭拆解和实测数据:官方的实测数据和差拆解报告。 4.maxwell prius2004建模仿真教程等:ppt资料一步一步教学怎么去建模 5.温升仿真分析,提供motor cad模型 ,磁路法; Maxwell有限元法; MotorCAD温仿真; 应力分析; Excell设计程序; Maxwell参数化仿真模型; 橡树岭拆解实测数据; Maxwelli Prius 2004建模仿真教程; 温升仿真分析; Motor CAD模型。,2004款Prius永磁同步电机设计报告:Excell程序与Maxwell有限元法融
基于Voronoi理论的维修站点选址算法研究.pdf
料箱输送线程序:PLC设备布局图及电气图纸集成系统(包含MultiControl控制卡等,采用STL开发,仅供学习参考),料箱输送线程序,带目的地跟踪,提供设备布局图和电气图纸以及博途程序。 程序语言较多使用了STL,程序仅供学习参考。 硬件配置:PLC:1515-2 PN HMI:TP700 Confort 主要设备有:英特诺直流辊筒电机,控制卡MultiControl;条码阅读器Sick CLV620; 和MiniLoad堆垛机通过Anybus模块通讯;称重模块品牌碧彩BIZERBA;还有使用丹佛斯变频器的提升机。 ,料箱输送线程序; 目的地跟踪; 设备布局图; 电气图纸; 博途程序; STL语言; PLC硬件配置; 英特诺直流辊筒电机; 控制卡MultiControl; 条码阅读器Sick CLV620; Anybus模块通讯; 称重模块碧彩BIZERBA; 丹佛斯变频器提升机。,"多设备集成:带目的地跟踪的料箱输送线博途程序"
1、资源内容地址:https://blog.csdn.net/2301_79696294/article/details/144634074 2、数据特点:今年全新,手工精心整理,放心引用,数据来自权威,且标注《数据来源》,相对于其他人的控制变量数据准确很多,适合写论文做实证用 ,不会出现数据造假问题 3、适用对象:大学生,本科生,研究生小白可用,容易上手!!! 4、课程引用: 经济学,地理学,城市规划与城市研究,公共政策与管理,社会学,商业与管理
2025网络安全法竞赛题题库及参考答案.pptx
CAN总线在小电流接地故障检测中的应用.pdf