Andorid中使用Jsoup解析庫解析XML、HTML、Dom節點---第三方庫學習筆記(三)
阿新 • • 發佈:2019-02-10
XML介紹:
XML簡介:
- XML,可擴充套件標記語言,標準通用標記語言的子集。
- 一種用於標記電子檔案使其具有結構性的標記語言。
- 它可以用來標記資料、定義資料型別
- 是一種允許使用者對自己的標記語言進行定義的源語言。
- 非常適合全球資訊網傳輸
- 提供統一方法描述和交換獨立於應用程式或供應商的結構化資料
XML的特點:
- XML是一種標記語言,很類似HTML
- XML的設計宗旨是傳輸資料,而非顯示資料
- XML標籤沒有被預定義,需要自行定義標籤
- XML被設計為具有自我描述性
XML是W3C的推薦標準
XML與HTML對比:
- XML和HTML是為不同目的而設計:
XML被設計為傳輸和儲存資料,其焦點是資料的內容
- HTML被設計用來顯示資料,其焦點是資料的外觀
- HTML旨在顯示資料,而XML旨在傳輸資料
2.XML僅僅是純文字
有能力處理純文字的軟體都可以處理XML。不過能夠讀懂XML的應用程式可以有針對的處理XML的標籤。標籤的功能性意義依賴於應用程式的特性。
3.XML沒有預定義的標籤
在HTML中使用的標籤(以及HTML的結構)是預定義的。HTML文件只使用在HTML標準中定義過的標籤。
XML的語法規則:
- 在XML中,省略關閉標籤是非法的,所有標籤都必須有關閉標籤。
- XML標籤對對大小寫敏感
- XML必須正確的巢狀
- XML文件必須有根元素
- XML的屬性值必須加引號
- XML中,空格會被保留
元素可以包含其他元素、文字、或者兩者的混合物。元素也可以擁有屬性。
<bookstore>
<book category="children">
<title>Harry Potter</title>
<author>JK.Rowing</author>
<year>2005</year>
<price>29.9</price>
</book>
</bookstore>
<bookstore>和<book >都擁有元素內容,因為他們包含了其他元素。
<author>只有文字內容,因為僅包含文字。
在上例中,只有<book>元素屬性(category="children")
使用JDK自帶的API(Document)解析和生成XML檔案:
需要解析的XML檔案:
<?xml version="1.0" encoding="utf-8"?>
<languages cat="it">
<lan id="1">
<name>Java</name>
<ide>Eclipse</ide>
</lan>
<lan id="2">
<name>Swift</name>
<ide>XCode</ide>
</lan>
<lan id="3">
<name>C#</name>
<ide>Visual Studio</ide>
</lan>
</languages>
package com.example.myxmltest;
import java.io.InputStream;
import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
private TextView text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
dealXML();//解析XML檔案
// createXML();//建立XML檔案
}
/**
* 建立XML檔案
*/
private void createXML() {
try {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document document = builder.newDocument();
//建立根節點元素
Element root = document.createElement("Languages");
//為根節點元素設定屬性值
root.setAttribute("cat", "it");
//第一個子節點
//建立子節點元素,併為子節點元素設定屬性值
Element lan1 = document.createElement("lan");
lan1.setAttribute("id", "1");
//建立子節點的子節點元素,併為其設定內容屬性值
Element name1 = document.createElement("name");
name1.setTextContent("Java");
Element ide1 = document.createElement("ide");
ide1.setTextContent("Eclipse");
//將這些內容節點新增到子節點中作為子節點的子節點
lan1.appendChild(name1);
lan1.appendChild(ide1);
//第二個子節點
//建立子節點元素,併為子節點元素設定屬性值
Element lan2 = document.createElement("lan");
lan2.setAttribute("id", "2");
//建立子節點的子節點元素,併為其設定內容屬性值
Element name2 = document.createElement("name");
name2.setTextContent("Swift");
Element ide2 = document.createElement("ide");
ide2.setTextContent("XCode");
//將這些內容節點新增到子節點中作為子節點的子節點
lan2.appendChild(name2);
lan2.appendChild(ide2);
//第三個子節點
//建立子節點元素,併為子節點元素設定屬性值
Element lan3 = document.createElement("lan");
lan3.setAttribute("id", "3");
//建立子節點的子節點元素,併為其設定內容屬性值
Element name3 = document.createElement("name");
name3.setTextContent("C#");
Element ide3 = document.createElement("ide");
ide3.setTextContent("Visual studio");
//將這些內容節點新增到子節點中作為子節點的子節點
lan3.appendChild(name3);
lan3.appendChild(ide3);
//將子節點新增到根節點中作為根節點的子節點
root.appendChild(lan1);
root.appendChild(lan2);
root.appendChild(lan3);
//新增根節點元素
document.appendChild(root);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty("encoding", "utf-8");
StringWriter sw = new StringWriter();
transformer.transform(new DOMSource(document), new StreamResult(sw));
text.setText(sw.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 用JDK自帶的API(Document)解析XML檔案
*/
private void dealXML() {
try {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
InputStream inputStream = getAssets().open("languages.xml");
Document document = builder.parse(inputStream);
//當前的element代表根節點中所有內容
Element element = document.getDocumentElement();
NodeList nodeList = element.getElementsByTagName("lan");
for (int i = 0; i < nodeList.getLength(); i++) {
Element lan = (Element) nodeList.item(i);
text.append(lan.getAttribute("id")+"\n");
text.append(lan.getElementsByTagName("name").item(0).getTextContent()+"\n");
text.append(lan.getElementsByTagName("ide").item(0).getTextContent()+"\n");
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void initView() {
text = (TextView) findViewById(R.id.text);
}
}
HTML、XML等Dom節點類解析庫的使用:
Jsoup簡介:
jsoup是一款Java的HTML解析器,可直接解析某個URL地址、HTML文字內容。它提供了一套非常省力的API,可通過DOM,CSS以及類似於JQuery的操作方法來取出和操作資料。
Jsoup特點:
- HTML、XML、自定義DOM格式文字解析
- 可操作HTML元素、屬性、文字
- 適用於採集解析網站HTML
- DOM解析功能非常強大
Jsoup基本用法:
- 分析Html或Dom文字的結點標籤結構
- 尋找你要解析的那個內容部分所在的結點標記
- 呼叫Jsoup API解析結點內容
程式碼演示:
- 使用Jsoup載入Html資料
- 使用Jsoup解析並提取HTML元素
- 使用Jsoup修改資料
- 使用Jsoup HTML文件清理
package com.test.Jsoup;
import java.io.File;
import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.safety.Whitelist;
import org.jsoup.select.Elements;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import com.example.myxmltest.R;
/**
* Jsoup的四個功能的基本使用方法
* @author Administrator
*
*/
public class JsoupTest extends Activity {
private String html = "<html><head><title>Jsoup的用法</title></head><body><p><a href='http://baidu.com'>這裡是Jsoup專案的相關文章</a></p></body></html>";
private String url = "http://baidu.com";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*
* 1.使用 Jsoup 載入 Html 資料功能
* 資料內容可以是:html文字、url、本地html
*/
//1.html文字
Document doc = Jsoup.parse(html);
//可以獲取到html中<title>的值
doc.title();
//2.url
try {
//通過GET方式請求
Document doc2 = Jsoup.connect(url).get();
//通過POST方法請求
// Document doc2 = Jsoup.connect(url).data("key","value").timeout(3000).post();
} catch (IOException e) {
e.printStackTrace();
}
//3.本地html
//獲取本地html檔案
File file = new File(Environment.getExternalStorageDirectory()+"/index.html");
//parse()方法引數解釋:1.html檔案 2.html的編碼格式(本地html檔案是什麼編碼就寫什麼編碼) 3.當本地html檔案中的圖片或者連結採用的是相對路徑時,就可以通過指定的baseUri替換路徑的字首。eg:.../baidu.png-->http://baidu.com/baidu.png
try {
Document doc3 = Jsoup.parse(file, "utf-8", "http://baidu.com");
} catch (IOException e) {
e.printStackTrace();
}
/*
* 2.使用 Jsoup 解析並提取 HTML元素功能
*/
Elements eles = doc.getElementsByTag("a");//將a標籤的列表儲存成元素集合
for (Element link : eles) {
//獲取a標籤中href的屬性值
String linkHref = link.attr("href");
//獲取a標籤中的文字值
String text = link.text();
}
//檢索元素功能
//檢索html檔案中的a標籤並且就有href屬性的a標籤列表儲存成元素集合
Elements elements = doc.select("a[href]");
//檢索html檔案中有img標籤的.png格式的圖片
Elements elements2 = doc.select("img[src$=.png]");
//檢索出元素名為className的div標籤的元素
Element element3 = doc.select("div.className").first();
/*
* 3.使用 Jsoup 修改資料屬性功能
*/
//對元素名為className的div標籤新增屬性,屬性名為key,屬性值為value
doc.select("div.className").attr("key","value");
//為元素名為className的div標籤新增屬性類,新增的屬性為:class="myclass"
doc.select("div.className").addClass("myclass");
//移除img標籤的onClick屬性
doc.select("img").removeAttr("onClick");
/*
* 4.使用 Jsoup HTML 文件清理功能
*/
String htmls = "";//不安全的一個html程式碼
String safe = Jsoup.clean(htmls, Whitelist.basic());//用基本的白名單將不安全的html程式碼轉換為安全的html
}
}
使用Jsoup來實現複雜的Html列表解析:
實現效果:
使用 Jsoup 實現對某網站新聞列表的採集解析
package com.test.jsoupdemo;
import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import com.example.myxmltest.R;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
/**
* 使用Jsoup解析HtmL新聞列表
*/
public class JsoupDemo extends Activity {
private String url = "http://mobile.csdn.net/";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
parseHtml();
}
}).start();;
}
//使用Jsoup解析html新聞列表
private void parseHtml() {
try {
Document doc = Jsoup.connect(url).get();
//將所有的新聞列表儲存為元素的集合
Elements elements = doc.select("div.unit");
for (Element element : elements) {
//獲取每一條新聞的標題<h1>標籤中的文字內容,因為每條新聞中只有一個h1,所以可以通過getElementsByTag("h1")獲取到
String title = element.getElementsByTag("h1").first().text();
//獲取每條新聞標題中的<h1>標籤中的超連結
String href = element.getElementsByTag("h1").first().getElementsByTag("a").first().attr("href");
//獲取每條新聞的新聞內容<dd>標籤中的文字內容
// String content = element.getElementsByTag("dd").first().text();
Log.i("tag", title);
Log.i("tag", href);
// Log.i("tag", content);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
原網頁截圖:
對應的網頁原始碼截圖:
根據上圖可以看出每條新聞的相同點:每條新聞的內容都是在<div class="unit">
標籤中。
通過上圖可以發現每條新聞中只有一個<h1>
標籤。
執行結果截圖: