zoukankan      html  css  js  c++  java
  • 【网络爬虫】【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


  • 相关阅读:
    Docker生态会重蹈Hadoop的覆辙吗?
    刘志强博士:专业涵养 奉献情怀
    Sublime Text3前端必备插件
    JVM性能调优监控工具jps、jstack、jmap、jhat、jstat、hprof使用详解
    jvm的stack和heap,JVM内存模型,垃圾回收策略,分代收集,增量收集(转)
    Eclipse安装MAT插件
    tomcat内存泄漏存入dump文件
    CSS中behavior属性语法简介
    get/post时中文乱码问题的解决办法
    Java序列化的机制和原理
  • 原文地址:https://www.cnblogs.com/DianaCody/p/5425649.html
Copyright © 2011-2022 走看看