Heritrix源码分析(十一) Heritrix中的URL--CandidateURI和CrawlURI以及如何增加自己的属性...

Url是爬虫的核心,因为爬虫就是依赖URL一层一层的抓取下去,最后完成整个抓取。Heritrix中的URL比较特殊,有以下继承关系(由于不对继承关系作介绍,所以这里就不画图了):

1)org.archive.crawler.datamodel.CrawlURI——>CandidateURI

2)org.archive.net.UURI——>org.archive.net.LaxURI

——>org.apache.commons.httpclient.URI——>java.net.URL

前面说过CrawlURI和CandidateURI的区别在于CrawlURI是由通过了调度器(Frontier)的CandidateURI转换而来的。下面就先介绍CnadidateURI(主要介绍相关属性):

Java代码 收藏代码
  1. publicstaticfinalintHIGH=1;//调度器调度等级:高
  2. publicstaticfinalintHIGHEST=0;//调度器调度等级:最高
  3. publicstaticfinalintMEDIUM=2;//调度器调度等级:中
  4. publicstaticfinalintNORMAL=3;//调度器调度等级:普通
  5. //URL字符串
  6. privateStringcachedCandidateURIString=null;
  7. //队列Key,不同队列有不同的classKey.其中相同classKey的CandidateURI则属于相同的队列
  8. privateStringclassKey;
  9. //是否强制访问,强制访问的话会重复抓取
  10. privatebooleanforceRevisit=false;
  11. //是不是种子
  12. privatebooleanisSeed=false;
  13. /**
  14. *灵活的属性列表,Heritrix在运行过程中需要保存不固定的属性和属性值,
  15. *同时扩展Heritrix属性也可以放在里面。不过需要特殊处理,等下单独介绍
  16. */
  17. privatetransientAListalist;
  18. /**
  19. *该值代表当前CandidateURI是如何从种子那里生成的,有如下生成方式:
  20. *P:预先处理URL,一般是DNS,如DNS:www.baidu.com
  21. *R:重定向URL
  22. *E:嵌入式URL,如Frame、src等
  23. *X:特殊嵌入式URL,如JS中的URL
  24. *L:一般意义上的URL,如<ahref="www.baidu.com">
  25. *该属性除了可以记录从种子那来源方式的话同时还可以记录深度,因为
  26. *该值是一层一层传递,每传递一层则增加一个以上字符.如此通过长度
  27. *可以判断当前URL属于种子的第几层从而做到控制抓取深度,如果当
  28. *前CandidateURI是种子,则该值为null
  29. */
  30. privateStringpathFromSeed;
  31. privateintschedulingDirective=NORMAL;//调度等级,默认为普通
  32. privatetransientUURIuuri;//URL
  33. privatetransientUURIvia;//来源URL
  34. privateCharSequenceviaContext;//来源URL内容

下面再介绍一下CrawlURI相关属性,前面说过CrawlURI和CandidateURI最大区别就是CrawlURI通过了调度器,这也就意味着CrawlURI会进入队列抓取,如此CrawlURI就会相比CandidateURI对很多属性来记录抓取情况,如处理器,下面请看代码以及注释:

Java代码 收藏代码
  1. //数组用户保存alist成员的key,使得URI处理期间可以持久化访问.这个list中的所有的key在传递下去的处理链后面都不会被清理掉
  2. privatestaticfinalList<Object>alistPersistentMember=newCopyOnWriteArrayList<Object>(
  3. newString[]{A_CREDENTIAL_AVATARS_KEY});
  4. //一个CrawlURI所允许的最大外链接数(就是该CrawlURI本身网页里所包含的链接数),默认为6000
  5. publicstaticfinalintMAX_OUTLINKS=Integer.parseInt(System.getProperty(
  6. CrawlURI.class.getName()+".maxOutLinks","6000"));
  7. //放弃的外链接个数(当一个URL抽取出来的链接数超过MAX_OUTLINKS时就放弃,然后本变量累加)
  8. transientprivateintdiscardedOutlinks=0;
  9. publicstaticfinalintUNCALCULATED=-1;//网页内容长度,默认值
  10. privateStringcachedCrawlURIString=null;//缓存的URL
  11. privatebyte[]contentDigest=null;//网页内容指纹,对内容进行MD5值,该对象可以用于对比该URL是否有更新
  12. privateStringcontentDigestScheme=null;//记录网页内容所采用算法,从配置文件里配置
  13. privatelongcontentLength=UNCALCULATED;//相应内容长度
  14. privatelongcontentSize=UNCALCULATED;//网页内容大小
  15. privateStringcontentType=null;//网页内容类型
  16. privateintdeferrals=0;//从先决条件URL延迟数
  17. privateintfetchAttempts=0;//获取URL的个数
  18. privateintfetchStatus=0;//获取URL内容状态,默认为0,表示没有尝试过
  19. transientObjectholder;//所属的队列(WorkQueue)
  20. intholderCost=UNCALCULATED;//成本
  21. transientObjectholderKey;//所属队列的classkey
  22. privatetransientHttpRecorderhttpRecorder=null;//记录网页内容
  23. transientprivatebooleanlinkExtractorFinished=false;//抽取是否成功,如果成功则该URL不会再被抽取
  24. transientprivateProcessornextProcessor;//下一个处理器
  25. transientprivateProcessorChainnextProcessorChain;//下一条处理链
  26. protectedlongordinal;//Crawl自增数目,用于广度优先抓取
  27. transientCollection<Object>outLinks=newHashSet<Object>();//该URL抽取到的所有的连接
  28. privatebooleanpost=false;//提交url是否post,对应HttpClient的HttpPost
  29. privatebooleanprerequisite=false;//是否有优先URL要处理,一般是DNS
  30. transientprivateintthreadNumber;//线程个数
  31. privateStringuserAgent=null;//用户代理,表名当前身份
  32. @Deprecated
  33. privateintembedHopCount=UNCALCULATED;
  34. @Deprecated
  35. privateintlinkHopCount=UNCALCULATED;//跃点数,表示来自种子的第几层,该值可以控制抓取深度

同时很多人在使用Heritrix的时候需要增加自己的属性,我之前也有这样的需求。不过那时是直接修改源代码增加几个属性,然后在抽取的时候将新的属性赋给抽取出来的URL即可。后来才发现完全没有这个必要,Heritrix已经提供了这样一个功能,可以自定义放入各种属性和属性值。同时Heritrix自己在运行过程中也是如此,把一些会动态变化的属性放入其中,如HttpStatus Code。下面就介绍下其相关原理以及如何使用这个功能:

1)原理:

CandidateURI里面有一个属性private transient AList alist;该属性实际上是一个HashTable,其中Key为属性,Value为属性值。如此一致贯穿整个抓取,可以随时动态读写。但由于该属性是transient,也就意味着HashTable里面的值不会被持久化,所以Heritrix在CrawlURI里面引入一个个变量来记录HashTable中需要持久化的Key,也就是我们所要持久化的属性了:private static final List<Object> alistPersistentMember = new CopyOnWriteArrayList<Object>( new String[] { A_CREDENTIAL_AVATARS_KEY });该属性类型为CopyOnWriteArrayList,也就是专门用于复制写的List,里面存放需要持久化的Key。所以当你需要某个HashTable中的某个Key持久化的时候,只需要在该变量里添加即可。

2)使用方法:

1.存放属性和属性值,变量可以按多种类型存放:

Java代码 收藏代码
  1. //放入类型为Int的值
  2. publicvoidputInt(Stringkey,intvalue){
  3. getAList().putInt(key,value);
  4. }
  5. //放入类型为Long的属性值
  6. publicvoidputLong(Stringkey,longvalue){
  7. getAList().putLong(key,value);
  8. }
  9. //放入类型为Object的属性值
  10. publicvoidputObject(Stringkey,Objectvalue){
  11. getAList().putObject(key,value);
  12. }
  13. //放入类型为String的属性值
  14. publicvoidputString(Stringkey,Stringvalue){
  15. getAList().putString(key,value);
  16. }

2.获得属性和属性值:

Java代码 收藏代码
  1. //获得属性的值,该值为Int类型
  2. publicintgetInt(Stringkey){
  3. returngetAList().getInt(key);
  4. }
  5. //获得属性的值,该值为Long类型
  6. publiclonggetLong(Stringkey){
  7. returngetAList().getLong(key);
  8. }
  9. //获得属性的值,该值为Object类型
  10. publicObjectgetObject(Stringkey){
  11. returngetAList().getObject(key);
  12. }
  13. //获得属性的值,该值为String类型
  14. publicStringgetString(Stringkey){
  15. returngetAList().getString(key);
  16. }

3.查看是否包含某个属性:

Java代码 收藏代码
  1. //查看是否包含某个属性
  2. publicbooleancontainsKey(Stringkey){
  3. returngetAList().containsKey(key);
  4. }

4.获得所有的属性:

Java代码 收藏代码
  1. //返回所有的属性值
  2. publicIteratorkeys(){
  3. returngetAList().getKeys();
  4. }

5.让某个属性持久化:

Java代码 收藏代码
  1. publicvoidmakeHeritable(Stringkey){
  2. @SuppressWarnings("unchecked")
  3. List<String>heritableKeys=(List<String>)getObject(A_HERITABLE_KEYS);
  4. if(heritableKeys==null){
  5. heritableKeys=newArrayList<String>();
  6. heritableKeys.add(A_HERITABLE_KEYS);
  7. putObject(A_HERITABLE_KEYS,heritableKeys);
  8. }
  9. heritableKeys.add(key);
  10. }

6.让某个属性不持久化:

Java代码 收藏代码
  1. publicvoidmakeNonHeritable(Stringkey){
  2. ListheritableKeys=(List)getObject(A_HERITABLE_KEYS);
  3. if(heritableKeys==null){
  4. return;
  5. }
  6. heritableKeys.remove(key);
  7. if(heritableKeys.size()==1){
  8. //onlyremainingheritablekeyisitself;disablecompletely
  9. remove(A_HERITABLE_KEYS);
  10. }
  11. }

以上6个介绍完全可以让你扩展自己的属性以及让他们持久化,如果还有其他问题,请留言,或者加入群:10447185

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值