Android Jsoup 爬取網頁數據

一不小心一個月又過去了,其實最近還是小忙小忙的,廢話不多說,直接進入今天的主題吧。

Jsoup -- Java HTML Parser, with best of DOM, CSS, and jquery.,看這個介紹就知道,這個就是方便咱們 JavaAndroid 來解析 HTML 的。

HTML 標簽

要去爬別人的 HTML 標簽的話,首先你肯定得有一定的 HTML 的基礎知識吧。比如說常用的標簽,標簽的相關屬性,這個就不多說了,有相關問題都可以在 www.w3school.com.cn 的網站解決一下。

加載網頁

最簡單的,直接加載一個網頁:

  Document document = Jsoup.connect("https://www.google.com").get();

那看到最后的 get() 方法聰明滴你一定就猜到還有一個對應的 post() 方法了吧。另外,http 請求的相關操作都是可以設置的,包括 header 請求參數,請求超時等等。除此之外,本地的文件(IO流)等都是可以直接解析的哈。

Document document = Jsoup.connect("https://android-arsenal.com")
        .timeout(5000)
        .cookie("cookie", "cxxx")
        .header("xx", "xx")
        .userAgent("")
        .get();

基本標簽解析

之后咱們就得到了一個 Document 的對象了。這個對象就是對整個請求網頁的封裝,相關內容都可以在里面獲取。

來吧,加入我們有下面一段html標簽需要解析:

<div class="project-info clearfix">
    <div class="header">
        <div class="title">
            <a href="/details/1/5442">RendererRecyclerViewAdapter</a>
            <a class="tags" href="/tag/199">Recycler Views</a>
        </div>
        <a class="badge free" href="/free">Free</a>
        <a class="badge new" href="/recent">New</a>
    </div>
    <div class="desc">
        <p>A single adapter for the whole project.</p>
        <ul>
        <li>Now you do not need to implement adapters for RecyclerView.</li>
        <li>You can easily use several types of cells in a single list.</li>
        <li>Using this library will protect you from the appearance of any business logic in an adapter.</li>
        </ul>
    </div>
    <div class="ftr l"><i class="fa fa-calendar"></i> Mar 17, 2017</div>
</div>

Jsoup 里面對于標簽的尋找使用的方法是 select() 方法,這個方法不要太強大了。咱們一步一步的來。

比如我們要在茫茫標簽中找到 <div class="project-info clearfix"> 的話,拿這里就是應該 findElementByClass() ,那么在 Jsoup 中是怎么定義這一塊的呢?

Jsoup-selector.png

哈哈,很easy嘛,那就是 document.select("div.project-info clearfix") 咯,當然不是這樣子的,等等 class 屬性里面這個空格是什么意思啊?是不是一臉懵逼?這里最終的寫法是 document.select("div.project-info.clearfix") 空格需要用 . 來處理。

      Elements select = document.select("div.project-info.clearfix");

這里得到是一個集合。我們接下來就需要遍歷這個集合,然后把里面的每一個標簽都拔出來。

title 部分的解析,這里是一個 <div> 里面嵌套了一個 <a> 的標簽。這里就涉及到了解析 <a> 標簽了。這里我們需要對應的 href,也需要對應的 textJsoup 提供了對應的兩個方法 attr()text()

Elements elements = e.select("div.title");
if (!elements.isEmpty()) {
    for (Element tittle : elements) {
        Element first = tittle.select("a[href]").first();
        if (first != null) {
            title = first.text();
            titleUrl = first.attr("href");
            System.out.println("名稱:" + title);
            System.out.println("具體地址:" + titleUrl);
        }

        Elements select1 = tittle.select("a.tags");
        if (!select1.isEmpty()) {
            tag = select1.text();
            tagUrl = select1.attr("href");
            System.out.println("tags:" + tag);
            System.out.println("tagUrl:" + tagUrl);
        }
    }
}   

嵌套解析

到這里, <div><a> 標簽的介紹基本搞定,接下來就是 <div class="desc"> 的解析了。

<div class="desc">
    <p>A single adapter for the whole project.</p>
    <ul>
    <li>Now you do not need to implement adapters for RecyclerView.</li>
    <li>You can easily use several types of cells in a single list.</li>
    <li>Using this library will protect you from the appearance of any business logic in an adapter.</li>
    </ul>
</div>

這里又多了 <ul><li> 了,其實道理是差不多的,但是這里它們既沒有 class 也沒有 id ,那這個我們應該這么去解析呢?

這里還是要回到 select() 方法,這里就需要使用到指定層級的方法了。

嵌套解析.png
        Elements select1 = e.select("div.desc > p");
        String s = select1.toString();

對于 <dt> <dd> 相關的標簽,就可以使用 + 相關的連接符了。例如我想要只解析 Tag 下面的對應的 Tag 名稱和相關的 url,這個應該怎么寫呢?

<dt>Tag</dt>
<dd><a href="/tag/9">Background Processing</a></dd>
<dt>License</dt>
<dd><a  rel="nofollow" target="_blank">Apache License, Version 2.0</a>
</dd>

代碼就是這樣的,這里一不小心就又引出了 select() 方法的嵌套高級寫法。

 Elements select4 = element.select("dt:contains(Tag) + dd");
select-高級.png

其實不用太多解釋啦,截圖里面描述的很清楚了。最后一個是可以支持正則的匹配。

同級相鄰解析

還有一種情況就是我們需要的標簽沒有具體的 id 或者 class,并且它沒有直接對應的父標簽或者某種固定的嵌套關系,例如下面這種情況:

<a id="favoriteButton" href="#" class="fa fa-star-o favorite tshadow" title="Add to favorites"></a> 
<a href="/details/1/5244">ImmediateLooperScheduler</a> <div id="githubInfoValue">

這里我們只需要解析到第二個 <a> 標簽,那么需要怎么處理呢?這里就需要使用到 nextElementSibling() 的方法了。

Element ssa = h1.select("a#favoriteButton").first();
Element element = ssa.nextElementSibling();
String title = element.text();

模糊解析

屬性限制.png

有時候我們只知道這個 <div> 是以 什么開頭或者是以什么結尾或者又是里面包含了某個單詞的,那么這個時候就需要使用模糊查找了。

Jsoup 中定義了這些情況的相關 select() 寫法,其中,以什么開頭,是使用 a[href^=http] ,以什么結尾使用 a[href$=.jpg] ,包含什么就是使用 a[href*=/search/]

javascript 解析

剛剛說的都是普通標簽及其內容,如果我要獲取js相關的標簽以及內容呢?其實也不難,只是最后不是使用text()的方法,而是使用data()的方法了。

就是 Jsoup 最主要的就是寫好這個 select() 方法,

final Elements script = document.select("script");

String js = script.first().data();

相關實戰

Android-Arsenal 這個網站不造大家伙兒有聽說過沒?這里給我們Android開發者提供了了一個信息交流展示平臺,實時更新一些Android相關的App,開發庫、以及Demo。然后,我看到它也有自己的客戶端,所以一時好奇也打算下載下來看看,結果,客戶端就是直接加載的網頁,關鍵是廣告滿天飛。這個就讓人不好受了(話說回來,人家不打廣告賺點兒錢做這個平臺干嘛呢。)

所以靈機一動,為什么我不自己搞一個 Android-Arsenal 的客戶端呢?這樣方便在手機上看到最新的東西嘛。所以就做了一個客戶端,而使用的就是Jsoup 來爬去的對應的網頁。然后就把對應 ads 的標簽都過濾了,所以是很清爽的啦。當然功能也只是先實現了一部分。喜歡的朋友可以點個星星或者下載使用喲!

最后來一波效果圖:

項目地址:https://github.com/lovejjfg/Android-Arsenal

1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg

---- Edit By Joe At 2017 03 18 ----

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,501評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,673評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,610評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,939評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,668評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,004評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,001評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,173評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,705評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,426評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,656評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,139評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,833評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,247評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,580評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,371評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,621評論 2 380

推薦閱讀更多精彩內容