网页内容的解析

网页内容的解析

Posted by dym on January 24, 2014

本文迁移自老博客,原始链接为 https://seven.blog.ustc.edu.cn/%e7%bd%91%e9%a1%b5%e5%86%85%e5%ae%b9%e7%9a%84%e8%a7%a3%e6%9e%90/

在使用heritrix爬虫抓取网页时,在工程目录下自动生成“jobs”文件夹,包含本次抓取任务。抓取下来网页以镜像方式存放,也就是将 URL 地址按“/”进行切分,进而按切分出来的层次存储。 爬取结束后,结果存放在工作目录下。如图: H{F]($MPOW6R~NV5VEDAI_N 如果想对抓取的内容进行处理并建立索引,需要解析这些文件中的html文件获取信息来进行索引,htmlparser就是专门用来进行解析网页内容的工具包。递归的对各文件进行解析,对每个文件夹下的html进行解析,提取出有用信息,然后存储到XML文件中,以供将来进行索引和搜索。使用了如下的方式递归的遍历文件夹,并使用readTextAndTitle方法提取文件标题和文本内容,然后对获取的字符串进行处理后后存到xml文件里。示例代码如下:

public class HTMLParserTest {
	private static ArrayList<String> filelist = new ArrayList<String>();
	static String filePath;
	static String name;
	static void getFiles(String filePath) {
		File root = new File(filePath);
		File[] files = root.listFiles();
		for (File file : files) {
			if (file.isDirectory()) {
				//递归调用
				getFiles(file.getAbsolutePath());
				filelist.add(file.getAbsolutePath());
				File directory = new File(file.getAbsolutePath());
				File[] htmlFiles = directory.listFiles(new FileNameSelector(
						"html"));
				for (File file1 : htmlFiles) {
					name = file.getAbsolutePath() + "/" + file1.getName();
					String path = file.getAbsolutePath() + "/"
					+ file1.getName();
					StringBuffer sbStr = new StringBuffer();
					BufferedReader reader = null;
					try {
						reader = new BufferedReader(new FileReader(new File(path)));
					} catch (FileNotFoundException e1) {
						e1.printStackTrace();
					}
					String temp = "";
					try {
						while ((temp = reader.readLine()) != null) {
							sbStr.append(temp);
							sbStr.append("");
						}
					} catch (IOException e) {
		 			        e.printStackTrace();
					}
					try {
						reader.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
					String result = sbStr.toString();
					// readAll(result);
					// readByHtml(result);
					try {
						readTextAndTitle(result);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
	public static void main(String args[]) throws Exception {
		filePath = "F:/workspace/MyHeritrix/jobs/sdufe-20130414121132012/mirror";
		getFiles(filePath);
	}
	// 读取文本内容和标题
	public static void readTextAndTitle(String result) throws Exception {
		resourceAdd add = new resourceAdd();
		Parser parser;
		NodeList nodelist;
		parser = Parser.createParser(result, "GB2312");
		NodeFilter textFilter = new NodeClassFilter(TextNode.class);
		NodeFilter titleFilter = new NodeClassFilter(TitleTag.class);
		OrFilter lastFilter = new OrFilter();
		lastFilter.setPredicates(new NodeFilter[] { textFilter, titleFilter });
		nodelist = parser.parse(lastFilter);
		Node[] nodes = nodelist.toNodeArray();
		String line = "暂无内容";
		Node node;
		String[] tmp = new String[9];
		int q = 0;
		int num = 0;
		for (int i = 0; i < nodes.length && i < 9; i++) {
			node = nodes[i];
			if (node instanceof TextNode) {
				TextNode textnode = (TextNode) node;
				line = textnode.getText();
			} else if (node instanceof TitleTag) {
				TitleTag titlenode = (TitleTag) node;
				line = titlenode.getTitle();
			}
			if (isTrimEmpty(line))
				continue;
			System.out.println(line);
			if (line.isEmpty())
				continue;
			else
				num++;
			if (line.length() > 10)
				line = line.substring(0, 9);
			tmp[q++] = line;
		}
		if (num < 8)
			return;
		else {
			tmp[5] = "2013-04-18";
			tmp[2] = "html";
			tmp[7] = "duyimin";
			tmp[8] = "暂无";
			tmp[0] = "1000";
			String a = "http://192.168.0.9:8080/resources/"
					+ name.substring(53);
			char[] b = new char[100];
			b = a.toCharArray();
			for (int i = 0; i < a.length(); i++) {
				if (b[i] == '\\')
					b[i] = '/';
			}
			tmp[6] = String.valueOf(b);
			add.xmldb(tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6],
					tmp[7], tmp[8]); //将数据存储到xml数据文件,供以后索引使用
		}
	}
	//去掉左右空格后字符串是否为空
	public static boolean isTrimEmpty(String astr) {
		if ((null == astr) || (astr.length() == 0)) {
			return true;
		}
		if (isBlank(astr.trim())) {
			return true;
		}
		return false;
	}
	//字符串是否为空:null或者长度为0.
	public static boolean isBlank(String astr) {
		if ((null == astr) || (astr.length() == 0)) {
			return true;
		} else {
			return false;
		}
	}
}

由于Heritrix是把爬取的内容照单全收,力求保存页面原貌,但是不会自动建立索引,所以我们才需要用如上述的方式对抓取的网页手动处理,这方面Nutch做的较好,Nutch只获取并保存可索引的内容,他是一个完整的搜索框架,包含了抓取和搜索的全过程,并有基于hadoop的分布式框架类似eclipse的插件机制,易于集成到自己的应用中。