【解析HTML】HTML解析,網絡爬蟲


一、概述

  曾幾時,我還是一個屌絲,一個在校大學生,高中的時候老師就對我們撒了一個慌,說...。人們稱它為一個善意的謊言,我卻傻傻信以為正。高三的時候努力拼搏了一段時間,可惜命運總是愛作弄人,高考考到了一個二流的大學,從此我告別了家鄉,踏上了大學校門,來到了一個鳥不生蛋但會拉屎的地方。剛來大學的時候,大一渾渾噩噩的度過,大門不錯,二門不邁,整體呆在宿舍打游戲,打了大半年的游戲,就那樣,大學里最美好的日子離我遠去。往事不堪回首,過了一年,如今已是學長了,作為一個學長,我不甘落后,於是乎上課努力聽講,下課沒事和同學去打球或是去圖書館學習html,css,javascript,java,過着四點一線的生活,在大二一年里拿了兩次獎學金。如今,已經是大三...,時間還在流逝,現在還是個屌絲,一個苦逼的大學生,還有事沒事喜歡爬各種網站,來滿足自己那點小小的虛榮心...。好了,扯淡時間過,該寫代碼了。

 原諒我那點發自內心的扯淡。下面我們開始進入今天的主題,HTML解析和網絡爬蟲。

什么是html,網絡爬蟲?

 什么是html這里就不多說了,那么什么是網絡爬蟲呢?是不是在網絡上怕的蟲?哈哈,簡直是弱爆了,在前面扯淡的內容中提到了,我喜歡爬各種網站,我爬過我學校的官網和教務管理系統,爬過各種IT網站,做了個簡單的新聞客戶端。網絡爬蟲其實是指自動地抓取萬維網信息的程序或者腳本,或者說是動態地抓取網站數據的程序。

怎樣解析html?

 這里我們通過Java解析html的利器Jsoup解析html,使用jsoup輕松搞定html解析,讓你從一個從矮窮挫瞬間變身高大上,高端大氣上檔次。

為什么要解析html?

 我們都知道現在網絡數據傳輸有三種常用的形式,xml,json(【JSON解析】JSON解析高手 )和html,我們的客戶端請求服務器,服務器通常給我們返回上面三種形式的數據。同時如果是個人開發,由於沒有自己的服務器,那么我們開發的應用程序就可以通過爬別人的網站解析html得到我們要的數據,當然,這種方式得到的數據不推薦,同時也存在太多的局限了,如:受網站的限制,解析困難等等。當然看了這篇文章解析就不是困難了,呵呵。

二、Jsoup和資源准備

jsoup介紹:

 jsoup 是一款Java 的HTML解析器,可直接解析某個URL地址、HTML文本內容。它提供了一套非常省力的API,可通過DOM,CSS以及類似於jQuery的操作方法來取出和操作數據。

主要功能:

  1. 從一個URL,文件或字符串中解析HTML;
  2. 使用DOM或CSS選擇器來查找、取出數據;
  3. 可操作HTML元素、屬性、文本;

jar包下載(兩種方式):

  1. 官網下載最新版:http://jsoup.org/download
  2. jsoup-1.8.3.jar(jar,doc和源碼)

jsoup更多信息查看官網:http://jsoup.org

三、HTML解析實戰

 新建一個Android項目(編碼設為UTF-8),將下載的jsoup的jar包添加到項目的libs目錄下,並添加到構建路徑中,這里由於不打算開發一個完整的應用,所以用的開發工具是我們更熟悉的eclipse,簡單點,不用Android Studio(as),用as也一樣。

作為測試數據,我們來爬一下這個網站:http://it.ithome.com/

訪問這個網站,可以看到現在最新的頁面顯示如下,當然,它的文章會不斷更新,這是寫文章的時候的頁面(頁面的一部分):

這里寫圖片描述

 我們的任務是把文章的相關信息抓下來,包括:

  1. 文章左邊的圖片url
  2. 文章的標題article
  3. 文章的內容簡介summary
  4. 底部的關鍵字tags
  5. 右上角的發表時間postime

如下圖:

這里寫圖片描述

OK,確定好了我們要抓取的信息后,我們通過瀏覽器調試工具Firebug打開查看該頁面的源碼找到我們關心數據的部分:

這里寫圖片描述

 這個ul里面的li第一個不是我們想要的數據外,其他的每個li中都保存了一篇文章的信息。選擇其中兩個看看。

這里寫圖片描述

下面我們可以編寫解析代碼了。

第一步:新建JavaBean,Article.java

package com.jxust.lt.htmlparse;

/**
 * 文章bean
 * @author lt
 *
 */
public class Article {

	private String title; // 標題
	private String summary; // 文章內容簡介
	private String imageUrl; // 圖片url
	private String tags; // 關鍵子
	private String postime; // 發表時間
	
	// setter...
	// getter...
	
	@Override
	public String toString() {
		return "Article [title=" + title + ", summary=" + summary
				+ ", imageUrl=" + imageUrl + ", tags=" + tags + ", postime="
				+ postime + "]";
	}
}

第二步:新建一個工具類,HtmlParseUtil.java,寫一個連接網絡並解析返回的html頁面的方法:

/**
	 * 請求網絡加載數據得到文章的集合
	 * @param url:網站url
	 */
	public static List<Article> getArticles(String url){
		List<Article> articles = new ArrayList<Article>();
		Connection conn = Jsoup.connect(url);
		try {
			// 10秒超時時間,發起get請求,也可以是post
			Document doc = conn.timeout(10000).get();
			// 1. 只要我們關心的信息數據,這里使用css類選擇器
			Element ul = doc.select(".ulcl").get(0);
			// 2. 得到所有的li,排除個別不是同種類型的數據
			Elements lis = ul.getElementsByTag("li");
			for(int i=1;i<lis.size();i++){ // 通過FileBug發現這個網頁里面第一個li不是我們要的類型,所以從1開始
				Article article = new Article();
				Element li = lis.get(i);
				// 數據1,得到圖片的url,通過img標簽的src屬性獲得
				Element img = li.getElementsByTag("img").first();
				// 獲取標簽的屬性值,參數為屬性名稱
				String imageUrl = img.attr("src");
				// 數據2,得到文章的標題
				Element h2 = li.getElementsByTag("h2").first();
				// 取h2元素下面的第一個a標簽的文本即為標題
				String title = h2.getElementsByTag("a").first().text();
				// 數據3,得到文章的發表時間,取h2元素下面的第一個span標簽的文本即為文章發表時間
				String postime = h2.getElementsByTag("span").first().text();
				// 數據4,得到文章內容簡介,取li下面第一個p標簽的文本
				String summary = li.getElementsByTag("p").first().text();
				// 數據5,得到文章的關鍵字,取li下面的class為tags的第一個元素的所有的a標簽文本
				Element tagsSpan = li.getElementsByClass("tags").first();
				Elements tags = tagsSpan.getElementsByTag("a");
				String key = "";
				for(Element tag : tags){
					key+=","+tag.text();
				}
				// 去掉key的第一個","號
				key = key.replaceFirst(",", "");
				
				article.setTitle(title);
				article.setSummary(summary);
				article.setImageUrl(imageUrl);
				article.setPostime(postime);
				article.setTags(key);
				articles.add(article);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		} 
		return articles;
	}

 在清單文件下添加請求網絡權限:

<uses-permission android:name="android.permission.INTERNET"/>

 說明:請求網絡得到Document對象后(不要導出包,是jsoup下的),通過select()方法帥選了class為ulcl的ul元素,該頁面下只有一個class為ulcl,ul下面第一個li不是我們要的,排除,然后得到每個li對象,每個li元素包含一篇文章的信息,解析重要方法說明:

  1. Document.select(String cssQuery):通過css選擇器獲取E元素集Elements
  2. Element.getElementsByTag(String tagName):通過標簽名稱獲取元素Elements
  3. Element.getElementsByClass(String className):通過標類選擇器獲取元素Elements
  4. Element.getElementById(String id):通過id獲取元素Element
  5. Element.attr(String attrName):通過屬性名獲取屬性值
  6. Element.text():獲取標簽元素的文本

 有js的DOM及JQuery編程經驗的人應該很容易理解上面的方法,更多的方法信息使用查看Jsoup官網文檔。

第三步:測試解析結果:

使用android單元測試:

  • 在AndroidManifest.xml添加instrumentation
<instrumentation android:targetPackage="com.jxust.lt.htmlparse" android:name="android.test.InstrumentationTestRunner"></instrumentation>
  • 在AndroidManifest.xml添加use-library
<uses-library android:name="android.test.runner"/>

新建一個測試類HtmlParseTest.java繼承AndroidTestCase

 寫一個測試方法:

	public void testParseHtml(){
		List<Article> articles = HtmlParseUtil.getArticles(url);
		for(int i=0;i<articles.size();i++){
			Log.e("result"+i, articles.get(i).toString());
		}
	}

 這里的url的值為:"http://it.ithome.com/"

打開模擬器運行測試方法 Run As Android JUnit Test

日志輸出結果:

這里寫圖片描述

...

這里寫圖片描述

可以看到我們得到了20條數據,我們來看看其中的一條

這里寫圖片描述

 可以看到文章標題,內容簡介,圖片url,關鍵字,發表時間5個我們關心的數據全都解析出來了。到這里html解析結束了,現在我們有了數據,那么我們就可以將數據顯示在listView中了(這里不會將數據顯示在ListView中,這個很簡單,一個布局一個適配器就搞定了,不懂的可以問),從而可以自己為網站寫個新聞客戶端了,把要的數據全都抓取下來,體驗一下將別人的數據為我所用的快樂,呵呵。

總結一下:

jsoup解析html的步驟:

  1. 得到Document對象:
  • 通過發送Jsoup的get或者post請求返回Document對象
  • 將html字符串轉換成Document對象(通過Jsoup.parse()方法):
  1. 使用Document.select()進行初步篩選數據

  2. 使用Element的一系列方法篩選出我們要的數據

注意:要對照頁面源碼解析,解析任何數據之前我們都得先知道要解析數據的結構,看着html頁面的源碼調用Document,Element等對象的相關方法怎么簡單怎么解析。

jsoup的get和post請求網絡在實際運用中使用不多,通常我會將jsoup和Volley,XUtils,Okhttp等著名的android網絡框架結合使用,即請求網絡用Volley等框架,解析用Jsoup,至少我就是這樣做的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM