這篇主要來(lái)講下近期做的一個(gè)項(xiàng)目-客戶(hù)端爬取網(wǎng)頁(yè)數(shù)據(jù)啄糙,用以向客戶(hù)個(gè)性化推薦產(chǎn)品笛臣。那么怎么在Android客戶(hù)端上將瀏覽的網(wǎng)頁(yè)爬取,提取有價(jià)值的數(shù)據(jù)呢隧饼?請(qǐng)耐心看下去.
一.爬取介紹
首先讓我們來(lái)了解下爬取這個(gè)東西沈堡。 一般來(lái)講對(duì)我們而言,需要抓取的是某個(gè)網(wǎng)站或者某個(gè)應(yīng)用的內(nèi)容燕雁,提取有用的價(jià)值诞丽,內(nèi)容一般分為兩部分,非結(jié)構(gòu)化的文本(e.g. HTML網(wǎng)頁(yè))拐格,或結(jié)構(gòu)化的文本(e.g. JSON數(shù)據(jù))僧免。
這邊要特殊介紹下HTML網(wǎng)頁(yè)。HTML基本上是傳統(tǒng)爬蟲(chóng)過(guò)程中最常見(jiàn)的捏浊,也就是大多數(shù)時(shí)候會(huì)遇到的情況懂衩,例如抓取一個(gè)網(wǎng)頁(yè),得到的是HTML金踪,然后需要解析一些常見(jiàn)的元素浊洞,提取一些關(guān)鍵的信息。HTML其實(shí)理應(yīng)屬于結(jié)構(gòu)化的文本組織胡岔,但是又因?yàn)橐话阄覀冃枰年P(guān)鍵信息并非直接可以得到法希,需要進(jìn)行對(duì)HTML的解析查找,甚至一些字符串操作才能得到姐军,所以還是歸類(lèi)于非結(jié)構(gòu)化的數(shù)據(jù)處理中铁材。
因?yàn)槲疫@期項(xiàng)目做的就是跟HTML網(wǎng)頁(yè)相關(guān),所以我很關(guān)心網(wǎng)頁(yè)內(nèi)容的來(lái)源奕锌,以及對(duì)應(yīng)的解析爬取方式著觉。
來(lái)源:
- 網(wǎng)頁(yè)包含內(nèi)容。一般來(lái)講基本上是靜態(tài)網(wǎng)頁(yè)已經(jīng)寫(xiě)死的內(nèi)容惊暴,或者動(dòng)態(tài)網(wǎng)頁(yè)饼丘,采用模板渲染,瀏覽器獲取到HTML的時(shí)候已經(jīng)是包含所有的關(guān)鍵信息辽话,所以直接在網(wǎng)頁(yè)上看到的內(nèi)容都可以通過(guò)特定的HTML標(biāo)簽得到
- JavaScript代碼加載內(nèi)容肄鸽。這種情況是由于雖然網(wǎng)頁(yè)顯示時(shí)卫病,內(nèi)容在HTML標(biāo)簽里面,但是其實(shí)是由于執(zhí)行js代碼加到標(biāo)簽里面的典徘,所以這個(gè)時(shí)候內(nèi)容在js代碼里面的蟀苛,而js的執(zhí)行是在瀏覽器端的操作,所以用程序去請(qǐng)求網(wǎng)頁(yè)地址的時(shí)候逮诲,得到的response是網(wǎng)頁(yè)代碼和js的代碼帜平,所以自己在瀏覽器端能看到內(nèi)容。
- Ajax異步請(qǐng)求梅鹦。這種情況是現(xiàn)在很常見(jiàn)的裆甩,尤其是在內(nèi)容以分頁(yè)形式顯示在網(wǎng)頁(yè)上,并且頁(yè)面無(wú)刷新齐唆,或者是對(duì)網(wǎng)頁(yè)進(jìn)行某個(gè)交互操作后嗤栓,得到內(nèi)容。
=========================
解析方式:
- CSS選擇器」坑剩現(xiàn)在的網(wǎng)頁(yè)樣式比較多茉帅,所以一般的網(wǎng)頁(yè)都會(huì)有一些CSS的定位,例如class锭弊,id等担敌,或者我們根據(jù)常見(jiàn)的節(jié)點(diǎn)路徑進(jìn)行定位。e.g. #id .class
- XPATH廷蓉。XPATH是一種頁(yè)面元素的路徑選擇方法,可以通過(guò)路徑表達(dá)式對(duì)XML文檔的節(jié)點(diǎn)進(jìn)行定位马昙。 比如—//*[@id=”finance”]桃犬,意思是找尋所有節(jié)點(diǎn)符合id為finance的節(jié)點(diǎn)。
- 正則表達(dá)式行楞。 用標(biāo)準(zhǔn)正則解析攒暇,一般會(huì)把HTML當(dāng)做普通文本,用指定格式匹配當(dāng)相關(guān)文本子房,適合小片段文本形用,或者某一串字符,或者HTML包含javascript的代碼证杭,無(wú)法用CSS選擇器或者XPATH田度。
介紹完這些,看官們?nèi)绻€有些疑問(wèn)解愤,可以去網(wǎng)上去豐富一下以上提的點(diǎn)镇饺,接下來(lái),看Android客戶(hù)端對(duì)爬取的實(shí)現(xiàn)
二.客戶(hù)端實(shí)現(xiàn)爬取
實(shí)現(xiàn)原理:在Android界面上送讲,開(kāi)啟一個(gè)webview奸笤,加載比如某郵箱或者某登錄網(wǎng)站的h5頁(yè)面惋啃,同時(shí)在 h5頁(yè)面加載完成后注入需要的腳本(可能多個(gè),可依情況拼接注入)监右,腳本會(huì)去監(jiān)聽(tīng)用戶(hù)的登錄動(dòng)作边灭,從而拿到用戶(hù)session,去爬取用戶(hù)需要的數(shù)據(jù),再通過(guò)js調(diào)native函數(shù)健盒,展示給用戶(hù)绒瘦!
這邊注入又分兩種方式:靜態(tài)與動(dòng)態(tài)
- 靜態(tài):在onPageFinished()方法中,讀取需要注入腳本文件味榛,字符串拼接后椭坚,使用webview.callJavascript(“javascript:”+jsStr,new ValueCallback())注入 **
- 動(dòng)態(tài):在onPageFinished()中,使用webview.loadUrl(“javascript:”+jsUrl);該方式可能會(huì)導(dǎo)致三星搏色,魅族手機(jī) libc奔潰,我偶爾會(huì)遇到善茎!
由于腳本內(nèi)容涉及公司開(kāi)發(fā)機(jī)密,目前不公開(kāi)频轿,大概實(shí)現(xiàn)思想:就是根據(jù)你所爬取的網(wǎng)頁(yè)垂涯,根據(jù)其特性,再符合你的需求航邢,通過(guò)CSS選擇器耕赘,以及Ajax請(qǐng)求,去模擬操作膳殷,得到數(shù)據(jù)并提取操骡。因?yàn)槲夷_本是通過(guò)javascript寫(xiě)的,通過(guò)jquery庫(kù)去模擬URL請(qǐng)求赚窃,得到data, 這時(shí)候的data就是平時(shí)看到網(wǎng)頁(yè)內(nèi)容的源代碼册招,依據(jù)上面提到的三種解析方式,基本都可以實(shí)現(xiàn)勒极。
三.腳本更新
因?yàn)镠TML網(wǎng)頁(yè)是來(lái)自各個(gè)公司是掰,不受自己控制,如果其版本改動(dòng)辱匿,我們所寫(xiě)的腳本不符合改動(dòng)后的網(wǎng)頁(yè)爬取键痛,這時(shí)候怎么辦呢?沒(méi)關(guān)系匾七,我們?cè)诳蛻?hù)端注入腳本時(shí)絮短,對(duì)我們的腳本做線(xiàn)上版本的更新,保證腳本在后續(xù)操作上的可行性昨忆!下面是腳本的安裝與熱更新流程圖戚丸,這邊就不多說(shuō)了!
安裝腳本:
更新腳本:
腳本爬取的介紹到這里就告一段落了,后續(xù)會(huì)繼續(xù)優(yōu)化流程限府,優(yōu)化爬取策略夺颤,有興趣的朋友可以找我討論下,謝謝胁勺!
如果覺(jué)得此文不錯(cuò)世澜,麻煩幫我點(diǎn)下“喜歡”。么么噠署穗!