Java网络爬虫学习记录(解析内容篇)

 

目录

 

4 网页内容解析

4.1 HTML

4.1.1 CSS选择器

4.1.2 Xpath语法(用于-选取节点)

4.1.3 Jsoup解析HTML

4.1.4 HtmlCleaner(HTML文档解析器)——支持Xpath语法

4.1.5 HtmlParser(HTML文档解析器)——支持CSS语法

4.2 JSON的解析(Fastjson)

4.2——实战案例


4 网页内容解析

4.1 HTML

4.1.1 CSS选择器

1——基础选择器(略过)


2——属性选择器 扩(可以指定具体标签的属性):div[title]

属性选择器
选择器(举例)含义
[title]选择带有title元素的所有属性
[^tit]查找属性前缀为titl的所有元素
[title="abc"]选择title="abc"的所有元素
[title~="ab"]选择title包含ab的所有元素
[title^="abc"]选择title开头是abc的所有元素
[title$="abc"]选择title结尾是abc的所有元素

3——组合选择器

组合选择器
选择器(举例)含义
div,p所有<div>、<p>
div p<div>内部的<p>
div.content>p<div>[class="content"]内的第一个<p>
div~p<div>之后所有<p>
div+p<div>之后第一个<p>

4——伪选择器

伪选择器
选择器(举例)含义
td:lt(3)小于3列的元素
div p:gt(2)包含2个以上<p>的<div>
form input:eq(1)包含1个<input>的<form>
div:has(p)包含<p>的<div>
div:not(p)不包含<p>的<div>
p:contains(abc)包含abc文本的<p>
div:nth-child(5)<div>内的第5个元素

 

4.1.2 Xpath语法(用于-选取节点)

Xpath语法
表达式(案例)含义
body<body>的全部子节点
/html根<html>
//div所有任意位置<div>
./p当前<p>
//a[@href]有href的<a>
//div[@id='course']id='course'的<div>
Xpath语法的组合使用
案例含义
//div[@id='ki']/h1<div id="ki">节点下的<h1>
//body/a[1]<body>下的第一个<a>
//body//a[last()]<body>下的最后一个<a>

4.1.3 Jsoup解析HTML

//document.select()选择节点元素;节点元素.attr()选择属性

1.解析URL加载的Document

package com.xp.climb.climb04.css;

import java.io.IOException;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;


public class JsoupCSS {

	public static void main(String[] args) throws IOException {
		//这里笔者使用Jsoup获取html文件
		Document doc = Jsoup.connect("http://www.w3school.com.cn/b.asp").timeout(5000).get(); 
		Elements elements = doc.select("[^titl]");
		Elements elements1 = doc.select("div#navsecond+div");
		System.out.println(elements1);
		//伪选择器---查找包含指定文本的元素
		Elements elements2 = doc.select("p:contains(JavaScript)");
		System.out.println(elements2);
		Elements elements3 = doc.select("div:only-child");
		System.out.println(elements3);
		Elements elements4 = doc.select("#maincontent > div:nth-child(5)");
		System.out.println(elements4);
	}

}

2.Jsoup遍历元素(XML

package com.xp.climb.climb04.xml;

import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class JsoupXML {
	public static void main(String[] args) throws IOException {
		//获取URL对应的HTML内容
		String url = "http://db.auto.sohu.com/cxdata/xml/sales/model/model1001sales.xml";
		Document doc = Jsoup.connect(url).timeout(5000).get();
		//Jsoup选择器解析
		//select()选择节点
		Elements sales_ele = doc.select("sales");
		for (Element elem:sales_ele) {
			//节点.attr()选择属性
			int salesnum=Integer.valueOf(elem.attr("salesnum"));
        	String date = elem.attr("date");
        	System.out.println("月份:" + date + "\t销量:" + salesnum);
        	
		}
	}
}

3. Jsoup获取元素的其他方法

除了select() 还有很多获取节点的方法——如下:
//Jsoup获取html
Document doc = Jsoup.connect("http://www.w3school.com.cn/b.asp").timeout(5000).get(); 
        //基于id获取元素
        Element element_id = doc.getElementById("course");
        //获取a标签 集合
        Elements elements_tag = doc.getElementsByTag("a");
        //获取属性有href的标签 集合
        Elements elements_A = doc.getElementsByAttribute("href");
        //获取class为joke的元素 集合
        Elements elements5 =doc.getElementsByClass("joke");
        //获取属性前缀为hre的元素 集合
        Elements elements_As = doc.getElementsByAttributeStarting("hre");
        //获取属性id=course的元素 集合
        Elements elements_Av = doc.getElementsByAttributeValue("id","course");
        //获取id=course的兄弟元素 集合
        Elements elements_Se = doc.getElementById("course").siblingElements();
        //获取id=course下一个兄弟元素
        Element element_Ns = doc.getElementById("course").nextElementSibling();
        //获取id=course上一个兄弟元素
        Element element_Ps = doc.getElementById("course").previousElementSibling();

 4.支持Xpath语法的JsoupXpath(需要导入相关依赖)自行了解

4.1.4 HtmlCleaner(HTML文档解析器)——支持Xpath语法

1. 导入依赖

<!-- HTML文档解析器 -->
        <dependency>
            <groupId>net.sourceforge.htmlcleaner</groupId>
            <artifactId>htmlcleaner</artifactId>
            <version>2.24</version>
        </dependency>

2. HtmlCleaner类和TagNode类

HtmlCleaner类的部分方法
方法说明
TagNode clean(String htmlContent)将String类型的HTML转化成TagNode
TagNode clean(File file,String charset)按照指定字符集将File中存储的HTML转化成TagNode
TagNode clean(File file)默认字符集转化成TagNode
TagNode clean(URL url,String charset)获取URL的HTMl内容(指定字符集),并转化成TagNode
TagNode clean(URL url)获取URL的HTMl内容(默认字符集),并转化成TagNode
TagNode clean(InputStream in,String charset)(指定)转化输入流HTML成TagNode
TagNode clean(InputStream in)(默认)转化输入流HTML成TagNode
TagNode类操作节点方法
方法说明
Object[] evaluateXPath(String xPath)Xpath语法获取Object数组
String getAttributeByName(String attName)属性名获取属性值
TagNode findeElementByName(String findName,boolean isRecursive)标签名获取节点

CharSequence getText()

获取节点中的文本
TagNode getParent()获取父节点
List<TagNode> getChildTagList()获取所有子节点,返回值-集合
boolean hasChildren()判断是否存在子节点

3. 操作案例 

package com.xp.climb.climb04.htmlcleaner;

import java.io.IOException;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.htmlcleaner.XPatherException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
public class HtmlcleanerTest1 {
	public static void main(String[] args) throws IOException, XPatherException {
		//使用Jsoup获取html文件
		Document doc = Jsoup.connect("http://www.w3school.com.cn/b.asp").
				timeout(5000).get();
		//转化成String格式
		String html =doc.html();
		//实例化HtmlCleaner
		HtmlCleaner cleaner = new HtmlCleaner();
		//转化成TagNode
		TagNode node = cleaner.clean(html);
		//----------------------------------------------------//
		//通过Xpath定位标题的位置,这里使用//h1和/h1的结果是一样的
        Object[]  ns = node.evaluateXPath("//div[@id='w3school']//h1");
        System.out.println("HTML中的标题是:\t" + ((TagNode)ns[0]).getText());
        Object[]  ns1 = node.evaluateXPath("//*[@id='w3school']/h1");
        System.out.println("HTML中的标题是:\t" + ((TagNode)ns1[0]).getText());
        //这里使用//a表示不考虑位置,如果使用/a获取不到内容
        Object[]  ns2 = node.evaluateXPath("//*[@id='course']/ul//a");
        for(Object on : ns2) {   //遍历获取课程名以及课程地址
            TagNode n = (TagNode) on;
            System.out.println("课程名为:\t" + n.getText() +
            		"\t地址为:\t" + n.getAttributeByName("href"));
        }
        //获取每个课程名称以及其对应的简介
        Object[]  ns3 = node.evaluateXPath("//*[@id='maincontent']//div");
		for (int i = 1; i < ns3.length-1; i++) {
        	TagNode n = (TagNode) ns3[i];
			//获取课程名称
        	String courseName = n.findElementByName("h2", true).getText().toString();
        	//循环遍历所有的p节点获取课程简介
			Object[] objarrtr = n.evaluateXPath("//p");
			String summary = "";
			for(Object on : objarrtr) {
				summary += ((TagNode) on).getText().toString();
			}
			System.out.println(courseName + "\t" + summary);
		}
	}
}

4.1.5 HtmlParser(HTML文档解析器)——支持CSS语法

1. 导入依赖

 <!-- HTML文档解析器 CSS-->
        <dependency>
            <groupId>org.htmlparser</groupId>
            <artifactId>htmlparser</artifactId>
            <version>2.1</version>
        </dependency>

2. 相关方法
HTMLParser先实例化Parser


Parser类常用--构造方法
方法说明
Parser()无参构造
Parser(Lexer lexer)通过Lexer构造Parser,-----案例中使用了
Parser(String resource)给一个URL或文件资源,构造Parser
Parser(URLConnection connection)使用URLConnection构造Parser

执行过滤任务(Filter)


常用的过滤器
方法说明
TagNameFilter(String name)根据标签名称进行过滤
NodeClassFilter(Class cls)根据类名进行过滤
HasAttributeFilter(String attribute)匹配出包含指定属性的节点
HasAttributeFilter(String attribute,String value)匹配出包含指定属性与属性值的节点
AndFilter(NodeFilter left,NodeFilter right)结合几种过滤条件的“与”过滤器
OrFilter(NodeFilter left,NodeFilter right)“或”过滤器
StringFilter(String pattern)根据模式对象进行过滤
RegexFilter(String pattern)根据正则表达式进行过滤
LinkStringFilter(String pattern)判断链接中是否有某个特定字符串
CssSelectorNodeFilter(String selector)根据CSS选择器获取节点(最常用)

③对节点进行操作


节点操作常用方法
方法说明
NodeList getChildren()获取子节点列表
Node getParent()获取父节点
Node getFirstChild()第一个子节点
Node getLastChild()最后一个子节点
Node getPreviousSibling()上一个兄弟节点
Node getNextSibling()下一个兄弟节点
String getText()节点数据(除了标签号< >)
String toPlainTextString()节点标签内的数据
String toHtml()返回节点对应的HTML片段
Page getPage()节点对应的Page对象
int getStartPosition()节点在HTML起始位置
int getEndPosition()节点在HTML结束位置
String getLink()节点的链接属性

Tip-1  关于AndFilter()“与”过滤的操作:

//过滤页面中的标签
NodeFilter filtertag= new TagNameFilter("ul");
//父节点包含ul
NodeFilter filterParent = new HasParentFilter(filtertag);
//包含li标签,并且li节点中包含id属性
NodeFilter filtername = new TagNameFilter("li");
NodeFilter filterId= new HasAttributeFilter("id");
//过滤器的并操作
NodeFilter filter = new AndFilter(filterParent,filtername);
NodeFilter filterfinal = new AndFilter(filter,filterId);
//选择匹配到的内容
NodeList list = parser.extractAllNodesThatMatch(filterfinal);

非常推荐的CSS选择器方式
 

package com.xp.climb.climb04.htmlparser;

import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import org.htmlparser.Node;
import org.htmlparser.Parser;
import org.htmlparser.filters.CssSelectorNodeFilter;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
public class HTMLParserTest3 {
	public static void main(String[] args) throws IOException, ParserException {
		//使用URLConnection请求数据
		URL url = new URL("https://www.w3school.com.cn/b.asp");
		URLConnection conn = url.openConnection();
		Parser parser = new Parser(conn);
		//css选择器进行过滤操作
		CssSelectorNodeFilter divFilter=new CssSelectorNodeFilter ("#course > ul > li");
		//选择匹配到的内容
		NodeList list = parser.extractAllNodesThatMatch(divFilter);
		//循环遍历
		for(int i=0; i<list.size();i++){
			//获取li的第一个子节点
			Node node = (Node)list.elementAt(i).getFirstChild();
			System.out.println( "链接为:" + ((LinkTag) node).getLink()
					+"\t标题为:" + node.toPlainTextString() );
		}
	}
}

4.2 JSON的解析(Fastjson

①导入依赖

<!-- JSON解析器    -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>

②操作JSON的三种方法案例

package com.xp.climb.climb04.fastjson.parse;


import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.xp.climb.climb04.model.BookModel;

public class FastjsonParseIArrayTest {

	public static void main(String[] args) {
		//json数组
		String json = "[{\"id\":\"01\",\"language\": \"Java\",\"edition\": \"third\",\"author\": \"Herbert Schildt\"},{\"id\":\"07\", \"language\": \"C++\",\"edition\": \"second\",\"author\": \"E.Balagurusamy\"}]";
		//使用fastjson解析Json数组
		//第一种方式---(泛型)---可操作JSON数组
		List<BookModel> listmodel = JSON.parseObject(json, new TypeReference<List<BookModel>>(){});
		//第二种方式---(数组)---
//		List<BookModel>  listmodel = JSON.parseArray(json, BookModel.class); 
		
		//json对象
		String json1 = "{\"id\":\"07\",\"language\": \"C++\",\"edition\": \"second\",\"author\": \"E.Balagurusamy\"}";		
		//第三种方式---(对象)---
//		BookModel model1 = JSON.parseObject(json1, BookModel.class);
		
		//输出数据
		for (BookModel model : listmodel) {
			System.out.println(model.getId() + "\t" + model.getLanguage() + 
					"\t" + model.getEdition());
		}
	}
}

4.2——实战案例

package com.xp.climb.climb04.demo;

import java.io.IOException;
import java.util.List;
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.HttpClients;
import org.apache.http.util.EntityUtils;
import com.alibaba.fastjson.JSON;
import com.xp.climb.climb04.model.CommentModel;

public class Demo {
	private static HttpClient httpClient = HttpClients.custom().build(); //初始化httpclient
	public static void main(String[] args) throws Exception {
		String url = "http://www.haodou.com/comment.php?do=list&callback=jQuery183016721538977115902_1531563599327&channel=recipe&item=853171&sort=desc&page=1&size=5&comment_id=0&cate=0&purify=common&_=1531563599599";
		//获取JSON数据
		String jsonstring = getJson(url);
		//解析JSON数据
		List<CommentModel> datalist = parseData(jsonstring);
		//输出数据
		for (CommentModel comm : datalist) {
			System.out.println(comm.getCommentId() + "\t" + comm.getItemId() + "\t" + comm.getContent());
		}
	}
	//获取JSON内容
	public static String getJson(String url) throws ClientProtocolException, IOException{
		HttpGet httpget = new HttpGet(url); //使用的请求方法
		//发出get请求
		HttpResponse response = httpClient.execute(httpget); 
		//获取网页内容流
		HttpEntity httpEntity = response.getEntity();  
		//以字符串的形式(需设置编码)
		String entity = EntityUtils.toString(httpEntity, "gbk");  
		//关闭内容流     
		EntityUtils.consume(httpEntity);     
		return entity;   //返回JSON
	}
	//解析Json内容
	public static List<CommentModel> parseData (String json) throws Exception{
		json = decode(json);  //将uncode码转化为中文
		//使用分割以及正则取代,处理成标准化JSON数组
		String jsondata  = "{"+json.split("data\":\\{")[2].split("\"avatar")[0].replaceAll("\"_\\d*[0-9]\":", "");
		String jsonStr = jsondata.substring(0, jsondata.length()-2);
		//将json数组解析成对象集合
		List<CommentModel>  datalis = JSON.parseArray("["+jsonStr.substring(1,jsonStr.length())+"]", CommentModel.class);
		return datalis;
	}
	//将uncode码转化为中文
	public static String decode(String unicodeStr) {
		if (unicodeStr == null) {
			return null;
		}
		StringBuffer retBuf = new StringBuffer();
		int maxLoop = unicodeStr.length();
		for (int i = 0; i < maxLoop; i++) {
			if (unicodeStr.charAt(i) == '\\') {
				if ((i < maxLoop - 5)
						&& ((unicodeStr.charAt(i + 1) == 'u') || (unicodeStr
								.charAt(i + 1) == 'U')))
					try {
						retBuf.append((char) Integer.parseInt(
								unicodeStr.substring(i + 2, i + 6), 16));
						i += 5;
					} catch (NumberFormatException localNumberFormatException) {
						retBuf.append(unicodeStr.charAt(i));
					}
				else
					retBuf.append(unicodeStr.charAt(i));
			} else {
				retBuf.append(unicodeStr.charAt(i));
			}
		}
		return retBuf.toString();
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值