网络爬虫(二)
在我们抓取到页面之后,还需要对页面进行解析。整个页面都是字符串的形式,可以使用字符串处理工具来解析页面,也可以使用正则表达式,但这些方法都会带来很大的开发成本。所以我们需要一款准们解析 html 页面的工具。
Jsoup
jsoup是一款 java 的 HTML 解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
主要功能:
1. 从URL,文件或字符串中解析HTML;
2. 使用DOM 或 CSS选择器来查找、取出数据;
3. 可操作 HTML元素、属性、文本(基本不使用)
使用:
1. 导入依赖坐标(jsoup、commons-io、commons-lang3)
2.1. 测试代码,解析URL
@Test public void urlFun() throws Exception { // 解析URL地址,参数:访问的url,访问时的超时时间 Document doc = Jsoup.parse(new URL("http://112.124.1.187/"),10000); // 使用标签选择器 String title = doc.getElementsByTag("title").first().text(); System.out.println(title); }
ps: 这里我们可以得出,Jsoup 可以代替 HttpClient 直接发起请求数据。但是我们往往不会这么做,因为实际开发中,需要使用到多线程、连接池、代理等等,而 Jsoup 对这些的支持并不是很好,所以我们一般把 Jsoup 仅仅作为 html 解析工具使用。
2.2. 测试代码,解析字符串
@Test public void strFun() throws Exception { // 从文件获取字符串 String content = FileUtils.readFileToString(new File("C:\\Users\\24360\\Desktop\\a.html"),"utf-8"); // 解析字符串 Document doc = Jsoup.parse(content); // 使用标签选择器 String title = doc.getElementsByTag("title").first().text(); System.out.println(title); }
2.3. 测试代码,解析文件
@Test public void strFun() throws Exception { // 解析文件 Document doc = Jsoup.parse(new File("C:\\Users\\24360\\Desktop\\a.html"),"gbk"); // 使用标签选择器 String title = doc.getElementsByTag("title").first().text(); System.out.println(title); }
3. 使用dom解析
@Test public void domTest() throws IOException { // 解析文件,获取Document对象 Document doc = Jsoup.parse(new File("C:\\Users\\24360\\Desktop\\a.html"),"gbk"); // 1.根据id获取元素: getElementById Element element1 = doc.getElementById("header"); // System.out.println(element1.text()); // 2.根据标签获取元素: getElementsByTag Element element2 = doc.getElementsByTag("span").get(2); System.out.println(element2.text()); // 3.根据class获取元素: getElementsByClass Element element3 = doc.getElementsByTag("class_a").get(0); System.out.println(element3.text()); // 4.根据属性获取元素: getElementsByAttribute Element element4 = doc.getElementsByTag("href").get(0); System.out.println(element4.text()); // 4.2 如果有多个属性名相同的情况,也可以根据属性-值 来获取 Element element5 = doc.getElementsByAttributeValue("href","http://www.baidu.com").get(0); System.out.println(element5.text()); }
4. 从元素中获取数据
如:<a id="baidu" class="class_a class_b" href="http://www.baidu.com">百度</a>
@Test public void attrTest() throws IOException { // 解析文件,获取Document对象 Document doc = Jsoup.parse(new File("C:\\Users\\24360\\Desktop\\a.html"),"gbk"); // 1.根据id获取元素: getElementById Element ele = doc.getElementById("baidu"); // 元素中获取数据 // 1.元素中获取id String strId = ele.id(); System.out.println(strId); // baidu // 2.元素中获取类名 String className = ele.className(); System.out.println("所有类名:" + className); // 所有类名:class_a class_b Set<String> classSet = ele.classNames(); for(String s : classSet){ // class_a class_b System.out.println(s); } // 3.元素中获取对应属性的值 String attr = ele.attr("href"); //http://www.baidu.com System.out.println(attr); // 4 获取所有属性 Attributes attrs = ele.attributes(); System.out.println(attrs.toString()); // id="baidu" class="class_a class_b" href="http://www.baidu.com" }
5.1 使用 Selector 选择器
tagname:通过标签查找元素,例:span
#id:通过id查找元素,例:#group
.class:通过类名查找元素,例:.class_a
[attribute]:通过属性查找元素,例:[abc]
[attr=value]:通过属性值查找元素,例:[class=sn]
如:
<a id="baidu" class="class_a class_b" href="http://www.baidu.com">百度</a>
<div abc="123">属性值</div>
@Test public void selectorTest() throws IOException { // 解析文件,获取Document对象 Document doc = Jsoup.parse(new File("C:\\Users\\24360\\Desktop\\a.html"),"gbk"); // tagname:通过标签查找元素,例:span Element e1 = doc.select("a").get(0); System.out.println(e1.text()); // 百度 // #id:通过id查找元素,例:#baidu Element e2 = doc.select("#baidu").get(0); System.out.println(e2.text()); // 百度 // .class:通过类名查找元素,例:.class_a Element e3 = doc.select(".class_a").get(0); System.out.println(e3.text()); // 百度 // [attribute]:通过属性查找元素,例:[abc] Element e4 = doc.select("[abc]").get(0); System.out.println(e4.text()); // 属性值 // [attr=value]:通过属性值查找元素,例:[abc=123] Element e5 = doc.select("[abc=123]").get(0); System.out.println(e5.text()); // 属性值 }
5.2 Selector 选择器组合使用
el#id:元素+ID,例:h3#group
el.class:元素+类名,例:h3.class_a
el[attr]:元素+属性名,例:span[abc]
任意组合:例:span[abc].class_a
ancestor child:查找某个元素下子元素,例:.class_a li,查找“.class_a”下的所有li
parent > child:查找某个父元素下的直接子元素(第一级)
parent > *:查找某个父元素下的所有直接子元素