티스토리 뷰

JTidy 라고 dirty HTML을 well formed XML로 바꿔주는 HTML 파서입니다.


사용법은 아주 간단한데,

			Tidy t = new Tidy();
			t.setInputEncoding("UTF-8");
			OutputStream out = null;

			Document doc = t.parseDOM(conn.getInputStream(), out);
와 같은 식으로 파싱을 하면 자바에 기본으로 있는 DOM 객체들을 이용해서 접근이 가능합니다. 

아래 소스는 특정 HTML의 트리 구조를 출력 해주는 간단한 예입니다.
private void printHtmlTree(String url) {
	try {
		URL u = new URL(url);
		URLConnection conn = u.openConnection();

		Tidy t = new Tidy();
		t.setInputEncoding("UTF-8");
		OutputStream out = null;

		Document doc = t.parseDOM(conn.getInputStream(), out);
		NodeList htmllist = doc.getElementsByTagName("html");
		if(htmllist.getLength() == 1){
			Node htmlnode = htmllist.item(0);
			traverseRecur(htmlnode, 0, "/");	
		}
		else{
			log("html node not found!");
		}			
	} catch (MalformedURLException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}
}

private void traverseRecur(Node n, int depth, String xpath) {
	printNodeTree(n, depth, xpath);
	
	NodeList childNodes = n.getChildNodes();
	HashMap siblingCounts = new HashMap();
	
	for(int i = 0; i < childNodes.getLength(); i++){
		Node child = childNodes.item(i);
		String childname = child.getNodeName();

		if(n.getNodeType() != Node.ELEMENT_NODE /*|| (childname.startsWith("#")*/ ){
			continue;	
		}
		
		Integer count = siblingCounts.get(childname);
		
		if(count != null){
			count += 1;
		}
		else{
			// insert sibling count
			count = 1;
		}
		siblingCounts.put(childname, count);

		String childpath = xpath + String.format("/%s[%d]", childname, count);
		
		traverseRecur(childNodes.item(i), depth + 1, childpath);
	}
}

private static final int MAX_TEXT_LEN = 10;
private void printNodeTree(Node n, int depth, String xpath) {
	String nodeName = n.getNodeName();
	String nodeValue = n.getNodeValue();
	String attr = "";
	
	// elem attr
	if(nodeName.equals("a") || nodeName.equals("img") || nodeName.equals("iframe")){
		try{
			Element e = (Element) n;

			String src = e.getAttribute("src");
			String href = e.getAttribute("href");

			if(src != "")
				attr = src;
			else if(href != "")
				attr = href;
		}catch(Exception ex) {
			log("cannot cast to element node!, %s", ex.getMessage());
		}
	}
	
	// print
	String indent = "";
	for(int i = 0; i < depth; i++){
		indent += "    ";
	}
	
	if(nodeValue.length() > MAX_TEXT_LEN){
		nodeValue = nodeValue.substring(0, MAX_TEXT_LEN);
	}
	
	log(indent + "name: %s, value: %s, (%s), attr: %s", nodeName, nodeValue, xpath, attr);
}
댓글
댓글쓰기 폼