一、垂直搜索介紹
1、垂直搜索--即需要抓去大量的網頁,分析其中的數據。垂直搜索更着重於正文內容模式分離,數據調整,相關鏈接分析,是一種結構化分析過程。
2、垂直搜索技術主要分爲兩個層次:模版級和網頁庫級
3、模版級是針對網頁進行模版設定或者自動生成模版的方式抽取數據,對網頁的採集也是針對性的採集,適合規模比較小、信息源少且穩定的需求,優點是快速實施、成本低、靈活性強,缺點是後期維護成本高,信息源和信息量小。
4、網頁庫級和模版方式最大的區別是對具體網頁不依賴,可針對任意正常的網頁信息採集信息抽取。缺點是其靈活性差、成本高。
垂直搜索大致需要以下技術:
1、信息採集技術
2、網頁信息抽取技術
3、信息的處理技術(重複識別、聚類、比較、分析等)
4、語意相關性分析
5、分詞
6、索引
二、使用HttpClient採集頁面
1、HTTPClient項目就是專門設計來簡化HTTP客戶端與服務器進行各種通訊編程。
2、HTTPClient是基於HttpCore實現的一個HTTP/1.1兼容HTTP客戶端,它提供了一系列可重用的客戶端身份驗證、HTTP狀態保持、HTTP鏈接管理module。功能豐富的HTTPClient同時兼具出色的可拓展性和健壯性,目前已經成爲了最爲流行的JavaHttp客戶端組件,爲開發Web瀏覽器、WebService客戶端提供了很大的便利。
下載地址: http://hc.apache.org/downloads.cgi
使用HttpClient
一般情況下,使用HttpClient需要以下5個步驟:
1、創建HttpClient的實例
2、創建某種連接方法的實例,在這裏是最常見的是Get和Post
3、調用第一步中創建好的HttpClient實例的execute方法,得到執行結果
4、釋放連接
5、對得到後的內容進行處理
下面來看兩個抓去網頁的實例
1、抓取搜索後的頁面然後保存
package com.qianyan.test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
public class TestHttpClient {
public static void main(String[] args) throws ClientProtocolException, IOException {
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet("http://www.baidu.com/s?wd=java");
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
InputStream ins = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(ins));
FileWriter writer = new FileWriter(new File("E:/baidu.htm"));
String strLine = reader.readLine();
while (null != strLine) {
writer.write(strLine);
strLine = reader.readLine();
}
writer.close();
ins.close();
reader.close();
httpClient.getConnectionManager().shutdown();
System.out.println("網頁生成完畢!");
}
}
1、抓取搜索後的頁面打印出來
package com.qianyan.test;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
public class TestHttpClient2 {
public static void main(String[] args) {
HttpClient httpClient = new DefaultHttpClient();
try {
//創建HttpGet
HttpGet httpGet = new HttpGet("http://www.ifeng.com");
System.err.println("executing request " + httpGet.getURI());
//執行get請求
HttpResponse response = httpClient.execute(httpGet);
//獲取響應實體
HttpEntity entity = response.getEntity();
System.err.println("======================================================");
//打印響應狀態
System.out.println(response.getStatusLine());
if (entity != null) {
//打印響應內容的長度
System.out.println("Response content lenght:"
+ entity.getContentLength());
String content = EntityUtils.toString(entity);
//解決HttpClient獲取中文亂碼 ,用String對象進行轉碼
System.out.println("Response content:"
+ new String(content.getBytes("ISO-8859-1"),"UTF-8"));
}
System.err.println("==========================================================");
} catch (Exception e) {
// TODO: handle exception
}finally{
//關閉連接,釋放資源
httpClient.getConnectionManager().shutdown();
}
}
}
三、使用JTidy
1、Tidy是W3C用來解析網頁的一個軟件包,可以方便地將HTML文檔轉化爲符合XML標準的文檔,由於XML可以方便地使用XSLT技術對內容進行抽取,所以使用Tidy配合XSLT可以方便地將各種網頁的內容抽取出來,保存成我們需要的格式。
2、通過JTidy可以方便地將標準的HTML網頁轉換爲XML的DOM對象,然後,通過XPath和XSTL將需要的內容抽取出來。
3、下載地址:http://sourceforge.net/projects/jtidy
4、JTidy的代碼實現iew plain
package com.qianyan.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import org.w3c.dom.Document;
import org.w3c.tidy.Tidy;
public class TestJTidy {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream(new File("E:/baidu.htm"));
InputStreamReader isr = new InputStreamReader(fis, "GBK");
FileOutputStream fos = new FileOutputStream(new File("E:/baidu.xml"));
Tidy tidy = new Tidy();
tidy.setXmlTags(true);
Document doc = tidy.parseDOM(isr, null);
tidy.pprint(doc, fos);
fos.close();
fis.close();
isr.close();
}
}
四、使用Nekohtml
1、Nekohtml是一個Java語言的HTML掃描器和標籤補全器(tag balancer),使得程序能解析HTML文檔並用標準的XML藉口來訪問其中的信息。這個解析器能夠掃描HTML文件並“修正”許多作者(人或機器)在編寫HTML文檔過程中常犯的錯誤。
2、Nekohtml能增補缺失的父元素、自動用結束標籤關閉相應的元素,以及不匹配的內嵌元素標籤。
NekoHTML的開發使用了Xerces Native Interface(XNI),後者是Xerces2的實現基礎。
3、下載地址:http://nekohtml.sourceforge.net/index.html
4、代碼實現:
package com.qianyan.test;
import java.io.BufferedReader;
import java.io.FileReader;
import org.cyberneko.html.parsers.DOMParser;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
public class TestNekoHTML {
public static String textExtractor(Node root){
//若是文本的話,直接返回
if (root.getNodeType() == Node.TEXT_NODE) {
return root.getNodeValue().trim();
}
if(root.getNodeType() == Node.ELEMENT_NODE) {
Element elmt = (Element) root;
//拋棄腳本
if (elmt.getTagName().equals("STYLE")
|| elmt.getTagName().equals("SCRIPT")
||elmt.getTagName().equals("BR"))
return "";
NodeList children = elmt.getChildNodes();
StringBuilder text = new StringBuilder();
for (int i = 0; i < children.getLength(); i++) {
text.append(textExtractor(children.item(i)));
}
return text.toString();
}
//對其他類型的節點,返回空值
return "";
}
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
DOMParser parser=new DOMParser();
BufferedReader reader=new BufferedReader(new FileReader("e:/baidu1.htm"));
parser.parse(new InputSource(reader));
Document doc=parser.getDocument();
Node body=doc.getElementsByTagName("body").item(0);
String str=textExtractor(body);
System.out.println(str);
}
}
五、使用HTMLParser
1、HTML Parser是一個對HTML進行分析的快速實時的解析器。
2、用法:
1)Visitor
2))Filter
3、下載地址:http://htmlparser.sourceforget.net/
4、代碼實現:
package com.qianyan.test;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.Tag;
import org.htmlparser.filters.NodeClassFilter;
import org.htmlparser.filters.OrFilter;
import org.htmlparser.filters.TagNameFilter;
import org.htmlparser.tags.ImageTag;
import org.htmlparser.tags.InputTag;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.tags.OptionTag;
import org.htmlparser.tags.SelectTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
import org.htmlparser.visitors.NodeVisitor;
import org.htmlparser.visitors.ObjectFindingVisitor;
import org.junit.Ignore;
import org.junit.Test;
public class TestHtmlParser {
/**
* 測試ObjectFindVisitor的用法
*/
@Test
// @Ignore
public void testImageVistor() {
try {
ImageTag imgLink;
ObjectFindingVisitor visitor = new ObjectFindingVisitor(
ImageTag.class);
Parser parser = new Parser();
parser.setURL("http://www.baidu.com");
parser.setEncoding(parser.getEncoding());
parser.visitAllNodesWith(visitor);
Node[] nodes = visitor.getTags();
for (int i = 0; i < nodes.length; i++) {
imgLink = (ImageTag) nodes[i];
StringBuilder sb = new StringBuilder();
sb.append(" ImageURL = " + imgLink.getImageURL());
sb.append("---- ImageLocation = " + imgLink.extractImageLocn());
sb.append("--- SRC = " + imgLink.getAttribute("SRC"));
System.out.println(sb.toString());
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 測試NodeVisitor的用法,遍歷所有節點
*/
@Test
@Ignore
public void testVisitorAll() {
try {
Parser parser = new Parser();
parser.setURL("http://www.baidu.com");
parser.setEncoding(parser.getEncoding());
NodeVisitor visitor = new MyNodeVisitor();
parser.visitAllNodesWith(visitor);
} catch (ParserException e) {
e.printStackTrace();
}
}
/**
* 測試NodeClassFilter用法
*/
@Test
@Ignore
public void testLinkTag(){
try{
NodeFilter filter = new NodeClassFilter(LinkTag.class);
Parser parser = new Parser();
parser.setURL("http://www.baidu.com");
parser.setEncoding(parser.getEncoding());
NodeList list = parser.extractAllNodesThatMatch(filter);
for(int i = 0; i < list.size(); i++){
LinkTag node = (LinkTag) list.elementAt(i);
System.out.println("Link is :" + node.extractLink());
}
}catch(Exception e){
e.printStackTrace();
}
}
/**
* 測試TagNameFilter用法
*/
@Test
@Ignore
public void testNodeFilter(){
try{
NodeFilter filter = new TagNameFilter("IMG");
Parser parser = new Parser();
parser.setURL("http://www.baidu.com");
parser.setEncoding(parser.getEncoding());
NodeList list = parser.extractAllNodesThatMatch(filter);
for(int i = 0; i < list.size(); i++){
System.out.println(" " + list.elementAt(i).toHtml());
}
}catch(Exception e){
e.printStackTrace();
}
}
/**
* 測試OrFilter的用法
*/
@Test
@Ignore
public void testOrFliter(){
NodeFilter inputFilter = new NodeClassFilter(InputTag.class);
NodeFilter selectFilter = new NodeClassFilter(SelectTag.class);
NodeList nodeList = null;
try{
Parser parser = new Parser();
parser
.setInputHTML("<head><title>OrFilter Test</title>"
+ "<link href=http://www.baidu.com/test01/css.css’ text=’text/css’ rel=’stylesheet’ />"
+ "<link href=http://www.baidu.com/test02/css.css’ text=’text/css’ rel=’stylesheet’ />"
+ "</head>"
+ "<body>"
+ "<input type=’text’ value=’text1′ name=’text1′/>"
+ "<input type=’text’ value=’text2′ name=’text2′/>"
+ "<select><option id=’1′>1</option><option id=’2′>2</option><option id=’3′>3</option></select>"
+ "<a href='http://www.baidu.com/'>baidu.com</a>"
+ "</body>");
parser.setEncoding(parser.getEncoding());
OrFilter lastFilter = new OrFilter();
lastFilter.setPredicates(new NodeFilter[]{selectFilter, inputFilter});
nodeList = parser.parse(lastFilter);
for(int i = 0; i <= nodeList.size(); i++){
if(nodeList.elementAt(i) instanceof InputTag){
InputTag tag = (InputTag)nodeList.elementAt(i);
System.out.println("OrFilter tag name is :" + tag.getTagName()
+ " ,tag value is:" + tag.getAttribute("value"));
}
if(nodeList.elementAt(i) instanceof SelectTag){
SelectTag tag = (SelectTag)nodeList.elementAt(i);
NodeList list = tag.getChildren();
for(int j = 0; j < list.size(); j++){
OptionTag option = (OptionTag)list.elementAt(j);
System.out.println("OrFilter Option"
+ option.getOptionText());
}
}
}
}catch(Exception e){
e.printStackTrace();
}
}
}
/**
* 內部實現了NodeVisitor下的visitTag方法
* @author Administrator
*
*/
class MyNodeVisitor extends NodeVisitor {
public void visitTag(Tag tag) {
System.out
.println("Tag name is :" + tag.getTagName()
+ "--- Class is :" + tag.getClass() + "---"
+ tag.getText());
}
}
使用htmlparser 獲得頁面中的所有超鏈接
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.filters.TagNameFilter;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
import org.htmlparser.visitors.HtmlPage;
public class ParserHtmlPage {
public NodeList parser(String url) throws ParserException{
/**根據url創建parser對象, || Parser parser = Parser.createParser(url,encoding)**/
Parser parser = new Parser(url);
/**設置編碼,必須與url編碼一樣,否則掛掉 **/
parser.setEncoding("utf-8");
/** 構建一個html頁面對象 **/
HtmlPage htmlPage = new HtmlPage(parser);
parser.visitAllNodesWith(htmlPage);
/** 獲取body下面所有的節點 **/
NodeList list = htmlPage.getBody();
/** 建立一個filter,用於過濾節點 **/
NodeFilter filter = new TagNameFilter("A");
/** 得到過濾後的節點 **/
list = list.extractAllNodesThatMatch(filter, true);
for(int c =0; c < list.size(); c ++){
LinkTag linkTag = (LinkTag) list.elementAt(c);
System.out.println("["+linkTag.getStringText()+"]"+linkTag.getAttribute("href"));//取得href屬性的值
//System.out.println(linkTag.getStringText());//取得鏈接的 文本
}
return list;
}
public static void main(String[] args) throws ParserException {
ParserHtmlPage pp = new ParserHtmlPage();
pp.parser("http://www.baidu.com");
}
}