Nutch源代码解读-二
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;} }
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;} }