Heritrix1.14源码分析(11) 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. public static final int HIGH = 1;                  //调度器调度等级:高  
  2. public static final int HIGHEST = 0;          //调度器调度等级:最高  
  3. public static final int MEDIUM = 2//调度器调度等级:中  
  4. public static final int NORMAL = 3//调度器调度等级:普通  
  5. //URL字符串  
  6. private String cachedCandidateURIString = null;  
  7.   
  8. //队列Key,不同队列有不同的classKey.其中相同classKey的CandidateURI则属于相同的队列  
  9. private String classKey;   
  10.   
  11. //是否强制访问,强制访问的话会重复抓取  
  12. private boolean forceRevisit = false;  
  13. // 是不是种子  
  14. private boolean isSeed = false;   
  15. /** 
  16.  * 灵活的属性列表,Heritrix在运行过程中需要保存不固定的属性和属性值, 
  17.   *同时扩展Heritrix属性 也可以放在里面。不过需要特殊处理,等下单独介绍 
  18.  */  
  19. private transient AList alist;  
  20.   
  21. /** 
  22.   * 该值代表当前CandidateURI是如何从种子那里生成的,有如下生成方式: 
  23.   * P:预先处理URL,一般是DNS,如DNS:www.baidu.com 
  24.    * R:重定向URL 
  25.    * E:嵌入式URL,如Frame、src等 
  26.   * X:特殊嵌入式URL,如JS中的URL 
  27.    * L:一般意义上的URL,如<a href="www.baidu.com"> 
  28.    * 该属性除了可以记录从种子那来源方式的话同时还可以记录深度,因为 
  29.   * 该值是一层一层传递,每传递一层则增加一个以上字符.如此通过长度 
  30.   * 可以判断当前URL属于种子的第几层从而做到控制抓取深度, 如果当 
  31.   * 前CandidateURI是种子,则该值为null 
  32.    */  
  33.  private String pathFromSeed;  
  34.   
  35. private int schedulingDirective = NORMAL; // 调度等级,默认为普通  
  36. private transient UURI uuri;          //URL           
  37. private transient UURI via;       //来源URL  
  38. private CharSequence viaContext;//来源URL内容  

 

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

Java代码   收藏代码
  1. //数组用户保存alist成员的key,使得URI处理期间可以持久化访问.这个list中的所有的key在传递下去的处理链 后面都不会被清理掉  
  2. private static final List<Object> alistPersistentMember = new CopyOnWriteArrayList<Object>(  
  3.         new String[] { A_CREDENTIAL_AVATARS_KEY });  
  4. // 一个CrawlURI所允许的最大外链接数(就是该CrawlURI本身网页里所包含的链接数),默认为6000  
  5. public static final int MAX_OUTLINKS = Integer.parseInt(System.getProperty(  
  6.         CrawlURI.class.getName() + ".maxOutLinks""6000"));  
  7. // 放弃的外链接个数(当一个URL抽取出来的链接数超过MAX_OUTLINKS时就放弃,然后本变量累加)  
  8. transient private int discardedOutlinks = 0;  
  9.   
  10. public static final int UNCALCULATED = -1//网页内容长度,默认值   
  11. private String cachedCrawlURIString = null//缓存的URL      
  12. private byte[] contentDigest = null//网页内容指纹,对内容进行MD5值,该对象可以用于对比该URL是否有更新  
  13. private String contentDigestScheme = null// 记录网页内容所采用算法,从配置文件里配置    
  14. private long contentLength = UNCALCULATED; //相应内容长度   
  15. private long contentSize = UNCALCULATED; //网页内容大小     
  16. private String contentType = null//网页内容类型   
  17. private int deferrals = 0;      //从先决条件URL延迟数  
  18.   
  19. private int fetchAttempts = 0;  // 获取URL的个数  
  20. private int fetchStatus = 0;    //获取URL内容状态,默认为0,表示没有尝试过      
  21. transient Object holder;        // 所属的队列(WorkQueue)  
  22. int holderCost = UNCALCULATED;  //成本  
  23. transient Object holderKey;     //所属队列的classkey  
  24. private transient HttpRecorder httpRecorder = null//记录网页内容      
  25. transient private boolean linkExtractorFinished = false//抽取是否成功,如果成功则该URL不会再被抽取  
  26. transient private Processor nextProcessor; // 下一个处理器  
  27. transient private ProcessorChain nextProcessorChain;// 下一条处理链     
  28. protected long ordinal; //Crawl自增数目,用于广度优先抓取  
  29. transient Collection<Object> outLinks = new HashSet<Object>();   //该URL抽取到的所有的连接  
  30. private boolean post = false// 提交url是否post,对应HttpClient的HttpPost  
  31. private boolean prerequisite = false//是否有优先URL要处理,一般是DNS  
  32. transient private int threadNumber; //线程个数  
  33. private String userAgent = null;    //用户代理,表名当前身份  
  34. @Deprecated  
  35. private int embedHopCount = UNCALCULATED;   
  36. @Deprecated  
  37. private int linkHopCount = 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. public void putInt(String key, int value) {  
  3.     getAList().putInt(key, value);  
  4. }  
  5. //放入类型为Long的属性值  
  6. public void putLong(String key, long value) {  
  7.     getAList().putLong(key, value);  
  8. }  
  9. //放入类型为Object的属性值  
  10. public void putObject(String key, Object value) {  
  11.     getAList().putObject(key, value);  
  12. }  
  13. //放入类型为String的属性值  
  14. public void putString(String key, String value) {  
  15.     getAList().putString(key, value);  
  16. }  

           2.获得属性和属性值:

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

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

Java代码   收藏代码
  1. //查看是否包含某个属性  
  2. public boolean containsKey(String key) {  
  3.     return getAList().containsKey(key);  
  4. }  

           4.获得所有的属性:

Java代码   收藏代码
  1. //返回所有的属性值  
  2. public Iterator keys() {  
  3.     return getAList().getKeys();  
  4. }  

           5.让某个属性持久化:

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

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

Java代码   收藏代码
  1. public void makeNonHeritable(String key) {  
  2.     List heritableKeys = (List) getObject(A_HERITABLE_KEYS);  
  3.     if (heritableKeys == null) {  
  4.         return;  
  5.     }  
  6.     heritableKeys.remove(key);  
  7.     if (heritableKeys.size() == 1) {  
  8.         // only remaining heritable key is itself; disable completely  
  9.         remove(A_HERITABLE_KEYS);  
  10.     }  
  11. }  

 

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

          

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值