Nutch源代码解读--2

Nutch0.9代码详细分析之2 主要分析网页爬取之后的页面处理

      前一次主要介绍了Nutch爬取网页的流程,在爬取完网页后返回一个ProtocalOutput对象,对爬行回来的信息进行了封装,包括ProtocalStatus返回的HTTP状态码,Content网页的主体内容等信息信息。在Fetcher中,如果我们继续往下看,会看到nutch根据不同的ProtocalStatus返回的状态码进行相应页面主体内容的分析处理。主要的代码如下,分析见注释 fetcherThread.run()的方法主体框架:

try {     boolean redirecting;//一个url的使用了重定向标记

            int redirectCount = 0;//记录一个url重定向次数必须小于maxRedirect

           //见分析 1 中的爬取主要流程,返回一个ProtocalOutput,status纪录了返回的HTTP状态码       switch(status.getCode()) {

              case ProtocolStatus.SUCCESS: // got a page

   //关键是output方法,该方法通过调用this.parseutil.parse(Content),利用HTMLParser对于爬取下来的网页进行分析,把结果的信息存储在Parse这个类中,包括了网页内容,标题,outlinks,metadata都在这一部进行封装.返回一个parseStatus类,表示这次网页分析是否成功

    // url:是这次爬取的目标url datum:CrawlDatum类,存储了关于这个url的爬取相关信息 status:网页爬取下来后,HTTP协议所返回的状态象200,300~400,404之类 CrawlDatus里面标识这个url被顺利爬取的static值

pstatus = output(url, datum, content, status,CrawlDatum.STATUS_FETCH_SUCCESS);

updateStatus(content.getContent().length);

if (pstatus != null && pstatus.isSuccess() &&pstatus.getMinorCode()

== ParseStatus.SUCCESS_REDIRECT) {

//如果url是重定向的,进行相应地处理存储新的url在newurl中,如果newurl和这次爬取的url相同

//那么放弃,如果不同则设置redirecting=true,在一次对这个newurl进行爬取,直到爬取成功或者redirectcount>maxredirect

String newUrl = pstatus.getMessage();

. . . break;

case ProtocolStatus.MOVED:// 如果网页进行了重定向情况下处理,同上分析

case ProtocolStatus.TEMP_MOVED: . . . break;

case ProtocolStatus.EXCEPTION:  // 出现了错误怎么办?

logError(url, status.getMessage());break;

// 网页没有找到几种情况,Content=null

case ProtocolStatus.GONE:           // gone

case ProtocolStatus.NOTFOUND:

case ProtocolStatus.ACCESS_DENIED:

case ProtocolStatus.ROBOTS_DENIED:

case ProtocolStatus.NOTMODIFIED:

            output(url, datum, null, status, CrawlDatum.STATUS_FETCH_GONE);

             break;           

default:. . . }

    //如果设置了重爬标记,那么重新爬取新的url           

} while (redirecting && (redirectCount < maxRedirect));

如果有人曾经和我一样,疑问nutch如何对网页进行分析呢?以上分析后关键就是output方法了。(当然自己写一个网页分析的不会多难,那我们具体看下nutch怎么做地?肯定是有帮助咯.)

Output:方法主体框架:它做了好多事情啊.

//key :分析该url的文本内容 datum:该url的相关信息 Content 该url文本内容 pstatus 返回的爬取状态传进来的code与pstatus是对应地    

ParseStatus output(Text key, CrawlDatum datum, Content content, ProtocolStatus pstatus, int status)

{. . . try {//在页面分析前对一个url的权重得分计算,默认是不变,这里如果想改进爬虫的侧重点的可以做点文章.^-^

scfilters.passScoreBeforeParsing(key, datum, content);} catch (Exception e) {}

Parse parse = null;//新建一个用于封装爬取内容主体的Parse类,涉及了ParseData类,封装信息包括了页面标题,主体,outlinks等.

if (parsing && status == CrawlDatum.STATUS_FETCH_SUCCESS) {

ParseStatus parseStatus;

        try {//这里使用HtmlParser进行主体内容的信息封装,当然具体有兴趣地可以继续看,涉及neko和tagsoup两种不同的方式去浏览文本内容,一个是基于Dom的一个是基于SAX的.nutch就是根据配置文件里的信息,默认使用neko基于Dom的方式给网页进行Dom树建立地.在HTMLParser.getParse(Content)方法中是详细的,根据DocumentFragment root这个根节点信息对Parse类进行封装从而返回这个Parse类

parse = this.parseUtil.parse(content); parseStatus = parse.getData().getStatus();

} catch (Exception e) {...}

...//这里要计算一个网页的签名??我不知道是什么意思.一个网页的签名是什么意思我还没弄懂.希望有朋友给我解释下

        byte[] signature = SignatureFactory.getSignature(getConf()).calculate(content, parse);. . .

        try {//在分析结束后重新计算得分

          scfilters.passScoreAfterParsing(key, content, parse);

        } catch (Exception e) {}

      try {

    //执行了分布式的任务,再以后我会对这个底层分布式文件系统Hadoop做更详细地分析咯.这个好难啃ORZ

        output.collect

          (key,new FetcherOutput(datum,storingContent ? content : null,

                             parse != null ? new ParseImpl(parse) : null));

      } catch (IOException e) {}

      //返回分析文本的状态.

      if (parse != null) return parse.getData().getStatus();else return null;} }

猜你喜欢

转载自wwkevin811.iteye.com/blog/1505803
今日推荐