JAVA jsoup 爬蟲 傻瓜入門實錄 (2-1) 選擇器 Selector 實務分解說明
JAVA jsoup 爬蟲 傻瓜入門實錄 (2-1) 選擇器 Selector 實務分解說明
這部分要講解的是個人常用的jsoup選擇器說明
上一篇我們講完各種型態解析成Document型態的方法實做
當我們解析成Document後 就可以開始做爬蟲的動作
爬蟲前我們應該先分析要抓取的網頁資料
你要抓的資料是在哪個div、哪個table
那個div是否有特定的id、class等等
由於公司我們抓匯的目的有個前提也要是能長時間自動抓匯
所以也要判斷要抓取的資料區域是否會隨時間改變 也盡量把所有可能的變因加上去 雖然每幾個月網頁資料或多或少還是有變化的地方 但是盡可能的縮小之後要修改程式的複雜程度
以下用一個以前的案子作範例 特別挑了一個較簡單的
要抓匯的位置就是基金產品裡的資料
分析後發現需要的資料都包含在這個class為”fund-jztable”的div tag中
因此第一目標就是先縮小區塊 把這個div先抓出來 後續再另外處理個別專案
String htmlPage = Jsoup.connect(“http://www.bdfund.com.cn/").get().toString();
Document doc = Jsoup.parse(htmlPage); //先做jsoup parse轉Document
這裡開始第一次使用到jsoup中非常強大的查詢功能:選擇器Selector
Elements divtags = doc.select(“div.fund-jztable”);
直接從案例說明 我們把剛剛做的步驟開始分解說明
如上述 我們要抓的tag是div 這個div的class是"fund-jztable"
因此我們從原本pasered的doc下select的方法 去選擇到div的tag
doc.select(“div”)
此時抓到的是網頁中所有div的tag 而經過select方法後出來的型態為Elements
我自己是把Elements想像成一個沒有間隔的array
Elements把所有div tag的區塊全部存入其中
一個div就是一個Element 所有的Element就組成此時Elements
這個是從案例面來講
總觀來講select方法找到的是你要指定的tag標籤(<a>,<div>,<table>….)
而這樣的寫法抓到的會是這個頁面所有包含你指定的標籤 包成一個Elements
Elements裡面並不是雜亂無章 你可以再額外篩出這堆相同標籤中 你要的指定專案
此時就講到第二部分
doc.select(“div.fund-jztable”)
這邊可以看到 有別於第一部分 這邊加入了class name 也就是我們真正要抓取的區塊
這種寫法你可以直接從網頁中一大堆相同tag中 找到你要的部分
但是前提是你必須判斷那個部分獨有的部分
如果這個class不只有這個地方出現 可能下面還有好幾個div同時也擁有這個class name 你抓出的將會是多個div區塊 而不是我們想要的單區塊
也因此 事前的分析非常重要 如果過於簡化剛開始分析的動作 很有可能做到一半才發現前面的步驟全都徒勞無功
上述案例 已經確認這個class name 是唯一 所以直接抓取這個class
而這是抓取class的寫法 實際上 在做抓取時 可能會要抓這個tag的id, attr等等
class
tagName.className //點前面為標籤名稱(a,div...) 點之後為class名稱
而下面再多提幾個我自己常用到的寫法
id
tagName#idName //#後接id名稱
//e.g doc.select(“a.myStatistics”)
attr
attr這邊必須多做敘述 attr也有許多寫法
純取所有指定attr屬性名稱
tagName[attrName] //[]中先寫入attr名稱
//e.g doc.select(“a[href]”)
指定attr屬性的值
tagName[attrName = attrValue] //[]中先寫入attr名稱 =後接value
//e.g doc.select(“a[href=google.com]”)
attr也可以搭配正規表示法 ^開頭 $結尾 *包含符號做查詢
[attrName ^= attrvalue] //以這個屬性值為開頭的所有元素
[attrName $= attrvalue] //以這個屬性值為結尾的所有元素
[attrName *= attrvalue] //包含這個屬性值的所有元素
[attrName ~= regularExpression] //正規表示法
這邊是我個人常用到的 還有更多寫法可以參考
這邊再補充一個點
其實可以把tag後面的所有name想成是attr 而value就是這個attr的value
舉個例
doc.select(“div.fund-jztable”)
你也可以想成
doc.select(“div[class=fund-jztable]”)
順便一提 其實這個select用法 用getElementsByTag也能達到相同的效果
doc.getElementsByTag(tagName);
doc.select(tagName);
兩者的差別在於 select可以直接一句話解決tag後面各種指定value的抓取
如果用getElementsBy可能又得先抓ByTag再拆開抓其他需要的value等等
不過因為getElementsBy可以ById,ByAttribute 可以直接跳過tag 找後面的value
像是Attribute也有詳細的方法可以做getElementsByAttributeStarting,ending,match等等
看自己習慣跟用途吧