package net.nutch.fetcher;
...
import org.cyberneko.html.parsers.*;
import org.xml.sax.*;
import org.w3c.dom.*;
import org.w3c.dom.html.*;
import org.apache.html.dom.*;
/* A simple fetcher. */
public class Fetcher {
....
private DOMFragmentParser parser = new DOMFragmentParser();
....
private void handleFetch(URL url, FetchListEntry fle, Http.Response response)
throws IOException, SAXException {
//判斷HTTP應(yīng)答包的類型,只放過html文件
String contentType = response.getHeader("Content-Type");
if (contentType != null && !contentType.startsWith("text/html"))
throw new IOException("Unknown content-type: " + contentType);
//創(chuàng)建文件片段對象
DocumentFragment node = new HTMLDocumentImpl().createDocumentFragment();
//解析HTML內(nèi)容
parser.parse(new InputSource(new ByteArrayInputStream(response.getContent())),node);
//取得全部文本內(nèi)容
StringBuffer sb = new StringBuffer();
getText(sb, node);
String text = sb.toString();
//取得標(biāo)題信息
sb.setLength(0);
getTitle(sb, node);
String title = sb.toString().trim();
//取得該頁所有的出鏈
ArrayList l = new ArrayList();
getOutlinks(url, l, node);
//顯示結(jié)果,存儲信息
Outlink[] outlinks = (Outlink[])l.toArray(new Outlink[l.size()]);
LOG.fine("found " + outlinks.length + " outlinks in " + url);
outputPage(new FetcherOutput(fle, MD5Hash.digest(response.getContent()),
true, title, outlinks),
new FetcherContent(response.getContent()),
new FetcherText(text));
}
private static void getText(StringBuffer sb, Node node) {
if (node.getNodeType() == Node.TEXT_NODE) {
sb.append(node.getNodeValue());//取得結(jié)點(diǎn)值,即開始與結(jié)束標(biāo)簽之間的信息
}
NodeList children = node.getChildNodes();
if ( children != null ) {
int len = children.getLength();
for ( int i = 0; i < len; i++ ) {
getText(sb, children.item(i));//遞歸遍歷DOM樹
}
}
}
private static boolean getTitle(StringBuffer sb, Node node) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
if ("title".equalsIgnoreCase(node.getNodeName())) {
getText(sb, node);
return true;
}
}
NodeList children = node.getChildNodes();
if (children != null) {
int len = children.getLength();
for (int i = 0; i < len; i++) {
if (getTitle(sb, children.item(i))) {
return true;
}
}
}
return false;
}
private static void getOutlinks(URL base, ArrayList outlinks, Node node) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
if ("a".equalsIgnoreCase(node.getNodeName())) {
StringBuffer linkText = new StringBuffer();
getText(linkText, node);
NamedNodeMap attrs = node.getAttributes();
String target= null;
for (int i= 0; i < attrs.getLength(); i++ ) {
if ("href".equalsIgnoreCase(attrs.item(i).getNodeName())) {
target= attrs.item(i).getNodeValue();//在DOM樹中,屬性是一個結(jié)點(diǎn)。
break;
}
}
if (target != null)
try {
URL url = new URL(base, target);
outlinks.add(new Outlink(url.toString(),linkText.toString().trim()));
} catch (MalformedURLException e) {
// don‘t care
}
}
}
NodeList children = node.getChildNodes();
if ( children != null ) {
int len = children.getLength();
for ( int i = 0; i < len; i++ ) {
getOutlinks(base, outlinks, children.item(i));//遞歸遍歷DOM樹
}
}
}
....
}