Android應用開發-小巫CSDN部落格用戶端Jsoup篇
距上一篇部落格已經過去了兩個星期,小巫也覺得非常抱歉,因為在忙着做另外一個項目,幾乎抽不出空來,這不小巫會把剩下的博文全部在國慶補上。本篇部落格将會給大家介紹如何使用Jsoup這個庫來解析我們的網頁,并且如何對我們想解析的網頁進行分析。 Jsoup這個庫的下載下傳位址:http://jsoup.org/download 筆者這裡使用的jsoup-1.7.2 下載下傳完之後複制到項目中的libs目錄下即可:
Jsoup的資料比較少,可供參考的可到其官網進行學習這個庫的使用:http://www.open-open.com/jsoup/ API查閱位址:http://jsoup.org/apidocs/
對這個庫的使用筆者也不是非常熟悉,就隻是簡單參考了文檔而完成了解析工作,是以下面的筆者的解析代碼也隻是提供參考,具體的解析方法,請認真檢視api文檔。 如何使用Jsoup這個庫不是重點,重點是如何對我們想解析的網頁進行分析,如何做到像以下的效果:
這裡可以看到首頁是擷取筆者部落格的博文清單,每一個條目都有對應的标題、博文摘要、釋出時間、閱讀數、評論數。這些内容就是通過解析首頁html頁面所得到的内容。
好,就是這樣的一個html頁面,大夥是不是很想把它搬到手機上呢,隻要你學會了如何分析html頁面,你可以把任何你想要的内容搬下來,隻要你抓取的網頁沒有做防扒取的措施。 筆者使用的浏覽器是Google Chrome,作為專業的IT人士,不用Chrome确實說不過去,按下F12,你就可以看到以下景象,感覺好興奮啊,可以去尋找你想要的寶藏了。是啊,逗比可以往下看了:
如果想解析一個網頁,還是得你自己以上面這種方式去看,找到你想要的内容。小巫是這樣做的,可以通過右鍵檢視元素,直接檢視對應的html源代碼,這樣你就知道内容對應的标簽是什麼了。因為小巫想獲得首頁的所有博文清單,是以我就找到博文的最外層的div标簽開始分析,我找到了id為article_list,然後接着找到了每條博文項的内容,确定下它們的具體的标簽,使用了什麼class,部落格可以通過class來擷取你想要的元素,然後取得元素的内容。
直接上代碼吧: [java] view plain copy
- public static List<BlogItem> getBlogItemList(int blogType, String str) {
- // Log.e("URL---->", str);
- List<BlogItem> list = new ArrayList<BlogItem>();
- // 擷取文檔對象
- Document doc = Jsoup.parse(str);
- // Log.e("doc--->", doc.toString());
- // 擷取class="article_item"的所有元素
- Elements blogList = doc.getElementsByClass("article_item");
- // Log.e("elements--->", blogList.toString());
- for (Element blogItem : blogList) {
- BlogItem item = new BlogItem();
- String title = blogItem.select("h1").text(); // 得到标題
- // System.out.println("title----->" + title);
- String description = blogItem.select("div.article_description")
- .text();
- // System.out.println("descrition--->" + description);
- String msg = blogItem.select("div.article_manage").text();
- // System.out.println("msg--->" + msg);
- String date = blogItem.getElementsByClass("article_manage").get(0)
- .text();
- // System.out.println("date--->" + date);
- String link = BLOG_URL
- + blogItem.select("h1").select("a").attr("href");
- // System.out.println("link--->" + link);
- item.setTitle(title);
- item.setMsg(msg);
- item.setContent(description);
- item.setDate(date);
- item.setLink(link);
- item.setType(blogType);
- // 沒有圖檔
- item.setImgLink(null);
- list.add(item);
- }
- return list;
- }
小巫通過class="article_item"擷取到所有的元素,也就是Element,然後周遊所有的元素,把每個元素我們需要的值取出來。我們可以定義一個實體類,比如文章項BlogItem,通過建立不同的BlogItem對象,然後最後添加到list當中,我們就可以把所有博文清單儲存下拉,下次取的時候,直接通過list來取即可。
我們可以看到使用Jsoup這個庫,隻需要那麼少的代碼就可以輕松擷取到我們想要的内容,編碼、效率啥都有,還等什麼,去用吧。
然後擷取博文詳細内容也是類似的,給定一個url,我們就可以同樣的方式去解析html代碼: [java] view plain copy
- public static List<Blog> getContent(String url, String str) {
- List<Blog> list = new ArrayList<Blog>();
- // 擷取文檔内容
- Document doc = Jsoup.parse(str);
- // 擷取class="details"的元素
- Element detail = doc.getElementsByClass("details").get(0);
- detail.select("script").remove(); // 删除每個比對元素的DOM。
- // 擷取标題
- Element title = detail.getElementsByClass("article_title").get(0);
- Blog blogTitle = new Blog();
- blogTitle.setState(Constants.DEF_BLOG_ITEM_TYPE.TITLE); // 設定狀态
- blogTitle.setContent(ToDBC(title.text())); // 設定标題内容
- // 擷取文章内容
- Element content = detail.select("div.article_content").get(0);
- // 擷取所有标簽為<a的元素
- Elements as = detail.getElementsByTag("a");
- for (int b = 0; b < as.size(); b++) {
- Element blockquote = as.get(b);
- // 改變這個元素的标記。例如,<span>轉換為<div> 如el.tagName("div");。
- blockquote.tagName("bold"); // 轉為粗體
- }
- Elements ss = detail.getElementsByTag("strong");
- for (int b = 0; b < ss.size(); b++) {
- Element blockquote = ss.get(b);
- blockquote.tagName("bold");
- }
- // 擷取所有标簽為<p的元素
- Elements ps = detail.getElementsByTag("p");
- for (int b = 0; b < ps.size(); b++) {
- Element blockquote = ps.get(b);
- blockquote.tagName("body");
- }
- // 擷取所有引用元素
- Elements blockquotes = detail.getElementsByTag("blockquote");
- for (int b = 0; b < blockquotes.size(); b++) {
- Element blockquote = blockquotes.get(b);
- blockquote.tagName("body");
- }
- // 擷取所有标簽為<ul的元素
- Elements uls = detail.getElementsByTag("ul");
- for (int b = 0; b < uls.size(); b++) {
- Element blockquote = uls.get(b);
- blockquote.tagName("body");
- }
- // 找出粗體
- Elements bs = detail.getElementsByTag("b");
- for (int b = 0; b < bs.size(); b++) {
- Element bold = bs.get(b);
- bold.tagName("bold");
- }
- // 周遊部落格内容中的所有元素
- for (int j = 0; j < content.children().size(); j++) {
- Element c = content.child(j); // 擷取每個元素
- // 抽取出圖檔
- if (c.select("img").size() > 0) {
- Elements imgs = c.getElementsByTag("img");
- System.out.println("img");
- for (Element img : imgs) {
- if (!img.attr("src").equals("")) {
- Blog blogImgs = new Blog();
- // 大圖連結
- if (!img.parent().attr("href").equals("")) {
- blogImgs.setImgLink(img.parent().attr("href"));
- System.out.println("href="
- + img.parent().attr("href"));
- if (img.parent().parent().tagName().equals("p")) {
- // img.parent().parent().remove();
- }
- img.parent().remove();
- }
- blogImgs.setContent(img.attr("src"));
- blogImgs.setImgLink(img.attr("src"));
- System.out.println(blogImgs.getContent());
- blogImgs.setState(Constants.DEF_BLOG_ITEM_TYPE.IMG);
- list.add(blogImgs);
- }
- }
- }
- c.select("img").remove();
- // 擷取部落格内容
- Blog blogContent = new Blog();
- blogContent.setState(Constants.DEF_BLOG_ITEM_TYPE.CONTENT);
- if (c.text().equals("")) {
- continue;
- } else if (c.children().size() == 1) {
- if (c.child(0).tagName().equals("bold")
- || c.child(0).tagName().equals("span")) {
- if (c.ownText().equals("")) {
- // 小标題,咖啡色
- blogContent
- .setState(Constants.DEF_BLOG_ITEM_TYPE.BOLD_TITLE);
- }
- }
- }
- // 代碼
- if (c.select("pre").attr("name").equals("code")) {
- blogContent.setState(Constants.DEF_BLOG_ITEM_TYPE.CODE);
- blogContent.setContent(ToDBC(c.outerHtml()));
- } else {
- blogContent.setContent(ToDBC(c.outerHtml()));
- }
- list.add(blogContent);
- }
- return list;
- }
擷取評論清單: [java] view plain copy
- public static List<Comment> getBlogCommentList(String str, int pageIndex,
- int pageSize) {
- List<Comment> list = new ArrayList<Comment>();
- try {
- // 建立一個json對象
- JSONObject jsonObject = new JSONObject(str);
- JSONArray jsonArray = jsonObject.getJSONArray("list"); // 擷取json數組
- int index = 0;
- int len = jsonArray.length();
- BlogCommentActivity.commentCount = String.valueOf(len); // 評論條數
- // 如果評論數大于20
- if (len > 20) {
- index = (pageIndex * pageSize) - 20;
- }
- if (len < pageSize && pageIndex > 1) {
- return list;
- }
- if ((pageIndex * pageSize) < len) {
- len = pageIndex * pageSize;
- }
- for (int i = index; i < len; i++) {
- JSONObject item = jsonArray.getJSONObject(i);
- String commentId = item.getString("CommentId");
- String content = item.getString("Content");
- String username = item.getString("UserName");
- String parentId = item.getString("ParentId");
- String postTime = item.getString("PostTime");
- String userface = item.getString("Userface");
- Comment comment = new Comment();
- comment.setCommentId(commentId);
- comment.setContent(content);
- comment.setUsername(username);
- comment.setParentId(parentId);
- comment.setPostTime(postTime);
- comment.setUserface(userface);
- if (parentId.equals("0")) {
- // 如果parentId為0的話,表示它是評論的topic
- comment.setType(Constants.DEF_COMMENT_TYPE.PARENT);
- } else {
- comment.setType(Constants.DEF_COMMENT_TYPE.CHILD);
- }
- list.add(comment);
- }
- } catch (JSONException e) {
- e.printStackTrace();
- }
- return list;
- }
具體使用細節可以參考筆者提供的源碼:http://download.csdn.net/detail/wwj_748/7912513
小巫已經把解析html的思路告訴大家啦,剩下如何來學習jsoup這個庫解析html就靠你們自己去做了。下一篇部落格預告,內建友盟社會化元件,詳細給大家介紹如何內建友盟提供的社會化元件SDK。