【網絡爬蟲】【java】微博爬蟲(四):數據處理——jsoup工具解析html、dom4j讀寫xml

        之前提到過,對於簡單的網頁結構解析,可以直接通過觀察法、手工寫正則解析,可以做出來,比如網易微博。但是對於結構稍微複雜點的,比如新浪微博,如果還用正則,用眼睛一個個去找,未免太麻煩了。

        本文介紹兩個工具包:解析html, xmljsoup,和讀寫xmldom4j

        工具包jsoup是解析html、xml的利器,利用jsoup可以快速讀取html等規範文檔格式的節點數據,比正則解析省事多了,而且自己寫正則容易考慮不周導致潛在bug,也很容易出錯。

        同時我們提取出來的微博數據直接存在txt文檔裏顯得結構層次不太清晰,也可以以xml的形式輸出,自定義節點,當然首先是得對xml格式有所瞭解,寫xml文件有個工具包dom4j。

        下面僅僅給出這兩個工具包在這個微博爬蟲項目中使用的例子,其實這兩個強大的工具包還有其他很多的用法,更多的應用詳見官方說明文檔。


一、jsoup解析HTML

        Jsoup是一個基於java的html解析器,可直接解析某個URL地址、HTML文本內容,其提供的API可以通過DOM, CSS,類jQuery的操作方法讀取和操縱數據。

Jsoup主要功能:

1.從一個url、文件或字符串解析html。

2.使用DOM或CSS選擇器查找、取出數據。

3.可以操作HTML的元素、屬性、文本。

        當然jsoup比其他解析器更有優勢的地方就是它的選擇器功能,很多解析只要一行代碼就搞定,而用其他工具包至少都要寫很多行。選擇器操作比如doc.select(“a[herf]”);選擇器select可以選擇你想要的任何元素。

 

在本項目中的代碼:

	public String parse(String html) {
		String s = "";
		Document doc = Jsoup.parse(html);
		Elements userNames = doc.select("dt[class].face > a");
		Elements userids = doc.select("span > a[action-data]");
		Elements dates = doc.select("a[date]");
		Elements tweetids = doc.select("dl[mid]");
		Elements tweets = doc.select("p > em");
		Elements forwardNums = doc.select("a:contains(轉發)");
		Elements commentNums = doc.select("a:contains(評論)");
		for(Element userName : userNames) {
			String attr = userName.attr("title");
			s += "<userName> " + attr + " </userName>";
		}
		for(Element userid : userids) {
			String attr = userid.attr("action-data");
			attr = attr.substring(attr.indexOf("uid="));
			Pattern p = Pattern.compile("[0-9]+");
			Matcher m = p.matcher(attr);
			if(m.find()) {
				attr = m.group();
			}
			s += "<userid> " + attr + " </userid>";
		}
		for(Element date : dates) {
			String attr = date.text();
			s += "<date> " + attr + " </date>";
		}
		for(Element tweetid : tweetids) {
			String attr = tweetid.attr("mid");
			s += "<tweetid> " + attr + " </tweetid>";
		}
		for(Element tweet : tweets) {
			String attr = tweet.text();
			s += "<tweetSentence> " + attr + " </tweetSentence>";
		}
		for(Element forwardNum : forwardNums) {
			String attr = forwardNum.text();
			if(attr.equals("轉發")) {
				attr = "0";
			}
			else {
				if(!attr.contains("轉發(")) {
					attr = "0";
				}
				else {
					attr = attr.substring(attr.indexOf("轉發(")+3, attr.indexOf(")"));
				}
			}
			System.out.println(attr);
			s += "<forwardNum> " + attr + " </forwardNum>";
		}
		for(Element commentNum : commentNums) {
			String attr = commentNum.text();
			if(attr.equals("評論")) {
				attr = "0";
			}
			else {
				if(!attr.contains("評論(")) {
					attr = "0";
				}
				else {
					attr = attr.substring(attr.indexOf("評論(")+3, attr.indexOf(""));
				}
			}
			System.out.println(attr);
			s += "<commentNum> " + attr + " </commentNum>";
		}
		//System.out.println(s);
		return s;
	}

二、dom4j寫出微博數據到xml

        在本項目中的代碼:

	public void writeVector2xml(Vector<String> vector, String saveXMLPath) throws IOException {
		int vectorSize = vector.size();
		String oneIniTweet;
		OutputFormat format = OutputFormat.createPrettyPrint();
		format.setEncoding("GB2312"); //xml被識別格式僅爲gb2312,默認utf8不被識別
		File f = new File(saveXMLPath);
		f.createNewFile(); //先建立一個空xml文件
		FileWriter fw = new FileWriter(f);
		org.dom4j.Document document = DocumentHelper.createDocument(); //建document對象實例
		org.dom4j.Element rootElement = document.addElement("tweets"); //節點增加方法
		rootElement.addAttribute("totalNumber", String.valueOf(vectorSize)); //設置屬性
		for(int j=0; j<vectorSize; j++) {
			oneIniTweet = vector.get(j);
			String userName = oneIniTweet.substring(oneIniTweet.indexOf("<userName> "), oneIniTweet.indexOf(" </userName>"));
			String userId = oneIniTweet.substring(oneIniTweet.indexOf("<userName> "), oneIniTweet.indexOf(" </userName>"));
			String prettyTime = oneIniTweet.substring(oneIniTweet.indexOf("<userName> "), oneIniTweet.indexOf(" </userName>"));
			String tweetSentence = oneIniTweet.substring(oneIniTweet.indexOf("<tweetSentence> "), oneIniTweet.indexOf(" </tweetSentence>"));
			org.dom4j.Element tweetElement = rootElement.addElement("tweet");
			tweetElement.addAttribute("userName", userName);
			tweetElement.addAttribute("userId", userId);
			tweetElement.addAttribute("prettyTime", prettyTime);
			tweetElement.setText(tweetSentence); // 設置節點文本內容
		}
		XMLWriter xw = new XMLWriter(fw, format);
		xw.write(document);
		xw.close();
	}

寫出的xml的結果:




原創文章,轉載請註明出處:http://blog.csdn.net/dianacody/article/details/39716637


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章