摘要:系列教程手把手教你寫(xiě)電商爬蟲(chóng)第一課找個(gè)軟柿子捏捏手把手教你寫(xiě)電商爬蟲(chóng)第二課實(shí)戰(zhàn)尚妝網(wǎng)分頁(yè)商品采集爬蟲(chóng)看完兩篇,相信大家已經(jīng)從開(kāi)始的小菜鳥(niǎo)晉升為中級(jí)菜鳥(niǎo)了,好了,那我們就繼續(xù)我們的爬蟲(chóng)課程。
系列教程:
手把手教你寫(xiě)電商爬蟲(chóng)-第一課 找個(gè)軟柿子捏捏
手把手教你寫(xiě)電商爬蟲(chóng)-第二課 實(shí)戰(zhàn)尚妝網(wǎng)分頁(yè)商品采集爬蟲(chóng)
看完兩篇,相信大家已經(jīng)從開(kāi)始的小菜鳥(niǎo)晉升為中級(jí)菜鳥(niǎo)了,好了,那我們就繼續(xù)我們的爬蟲(chóng)課程。
上一課呢一定是因?yàn)閷?duì)手太強(qiáng),導(dǎo)致我們并沒(méi)有完整的完成尚妝網(wǎng)的爬蟲(chóng)。
吭吭~,我們這一課繼續(xù),爭(zhēng)取徹底搞定尚妝網(wǎng),不留任何遺憾。
我們先回顧一下,上一課主要遺留了兩個(gè)問(wèn)題,兩個(gè)問(wèn)題都和ajax有關(guān)。
1、由于是ajax加載下一頁(yè),導(dǎo)致下一頁(yè)url并不會(huì)被系統(tǒng)自動(dòng)發(fā)現(xiàn)。
2、商品頁(yè)面的價(jià)格是通過(guò)ajax加載的,我們直接從網(wǎng)頁(yè)中獲取不到信息本身。
好了,我們先解決第一個(gè)問(wèn)題:
第一個(gè)問(wèn)題實(shí)際上是一個(gè)爬蟲(chóng)中比較常見(jiàn)的問(wèn)題,即url的發(fā)現(xiàn),默認(rèn)情況下,URL的發(fā)現(xiàn)是神箭手云爬蟲(chóng)框架自動(dòng)處理的,但是如果在ajax的情況下,框架則無(wú)從發(fā)現(xiàn)url,這個(gè)時(shí)候就需要我們自己手動(dòng)處理url的發(fā)現(xiàn),這里,神箭手給我們提供了一個(gè)很方便的回調(diào)函數(shù)讓我們來(lái)自己處理url的發(fā)現(xiàn):
onProcessHelperUrl(url, content, site)
這個(gè)回調(diào)函數(shù)有兩個(gè)參數(shù),分別是當(dāng)前處理的頁(yè)面對(duì)象和整個(gè)爬取站的對(duì)象,我們可以通過(guò)獲取頁(yè)面對(duì)象的內(nèi)容來(lái)分析是否有我們需要的新一頁(yè)的url,通過(guò)site.addUrl()方法加入到url隊(duì)列中既可。這里我們可以看到,當(dāng)超出頁(yè)數(shù)的時(shí)候,尚妝網(wǎng)會(huì)給我們返回一個(gè)這樣的頁(yè)面,我們就知道頁(yè)數(shù)超過(guò)了,不需要在加入新的頁(yè)url:
這個(gè)頁(yè)面我們很好判斷,只需要看內(nèi)容中是否有"無(wú)匹配商品"關(guān)鍵字既可。
這里我們需要一些基礎(chǔ)的js能力,代碼如下:
configs.onProcessHelperUrl = function(url, content, site){ if(!content.indexOf("無(wú)匹配商品")){ //如果沒(méi)有到最后一頁(yè),則將頁(yè)數(shù)加1 var currentPage = parseInt(url.substring(url.indexOf("&page=") + 6)); var page = currentPage + 1; var nextUrl = url.replace("&page=" + currentPage, "&page=" + page); site.addUrl(nextUrl); } }
原理很簡(jiǎn)單,如果內(nèi)容中沒(méi)有無(wú)匹配商品這個(gè)關(guān)鍵詞的時(shí)候,則把當(dāng)前頁(yè)面的下一頁(yè)加入的待爬隊(duì)列中。
好了,ajax分頁(yè)問(wèn)題徹底解決,下面來(lái)看這個(gè)最棘手的ajax內(nèi)容加載的問(wèn)題,也就是如何獲取到商品頁(yè)面中的價(jià)格信息
首先,遇到這類(lèi)問(wèn)題,我們通常有兩個(gè)思路:
1、通過(guò)js引擎將整個(gè)頁(yè)面渲染出來(lái)之后,在去做內(nèi)容抽取,這個(gè)方案對(duì)于一些復(fù)雜js頁(yè)面是唯一解決方案,用神箭手來(lái)處理也很簡(jiǎn)單,不過(guò)由于需要執(zhí)行js,導(dǎo)致抓取速度很慢,不到不得已情況,我們先不使用這個(gè)核武器
2、通過(guò)剛剛處理分頁(yè)的經(jīng)驗(yàn),我們可以預(yù)先分析ajax請(qǐng)求,然后將這一步多出來(lái)的請(qǐng)求和原來(lái)的頁(yè)面請(qǐng)求做一個(gè)關(guān)聯(lián)。這種方案適合比較簡(jiǎn)單的js頁(yè)面中。
OK,介紹完思路,根據(jù)經(jīng)驗(yàn),我們感覺(jué)尚妝網(wǎng)的ajax加載并沒(méi)有十分復(fù)雜,所以我們選擇方案二來(lái)處理這種ajax頁(yè)面加載。
同樣的,首頁(yè)我們通過(guò)chrome開(kāi)發(fā)者工具,抓取到這個(gè)ajax請(qǐng)求,這里教大家一個(gè)小竅門(mén),開(kāi)發(fā)者工具中,可以篩選請(qǐng)求對(duì)象未xhr,這種就是異步請(qǐng)求,我們就很容易發(fā)現(xiàn)我們的嫌疑url:
http://item.showjoy.com/product/getPrice?skuId=22912
我們?cè)陧?yè)面中找一下這個(gè)22912怎么提取最方便,我們很快就發(fā)現(xiàn)了一個(gè)標(biāo)簽:
這個(gè)標(biāo)簽很干凈,獲取的xpath也很簡(jiǎn)單:
//input[@id="J_UItemId"]/@value
這樣就好辦了,我們?cè)倏聪逻@個(gè)頁(yè)面請(qǐng)求的結(jié)果是什么:
{"count":0,"data": {"discount":"6.2","discountMoney":"43.00","originalPrice":112,"price":"69.00","showjoyPrice":"69.00"},"isRedirect":0,"isSuccess":0,"login":0}
可以看出來(lái),是一個(gè)典型的json對(duì)象,這個(gè)就好辦了,神箭手中給我們提供了通過(guò)jsonpath提取內(nèi)容的方式,可以很簡(jiǎn)單的提取到價(jià)格對(duì)象,即price對(duì)應(yīng)的值。
那最后我們?cè)趺床拍荜P(guān)聯(lián)這個(gè)請(qǐng)求呢?這里也是框架中提供的一個(gè)方案,叫做attachedUrl,專(zhuān)門(mén)用來(lái)解決關(guān)聯(lián)請(qǐng)求的請(qǐng)求的問(wèn)題,也就是某一個(gè)字段的值可以通過(guò)一個(gè)關(guān)聯(lián)請(qǐng)求的內(nèi)容中抽取出來(lái)。語(yǔ)法我就不介紹了,直接上代碼吧:
{ name: "skuid", selector: "http://input[@id="J_UItemId"]/@value", }, { name: "price", sourceType: SourceType.AttachedUrl, attachedUrl: "http://item.showjoy.com/product/getPrice?skuId={skuid}", selectorType: SelectorType.JsonPath, selector: "$.data.price", }
簡(jiǎn)單介紹一下attachedUrl的用法,首先我們要設(shè)置sourceType為attachedUrl,同時(shí)我們要設(shè)置一個(gè)attachedUrl,即為關(guān)聯(lián)請(qǐng)求的地址,其中由于有一個(gè)值是動(dòng)態(tài)的,所以我們需要在這個(gè)抽取項(xiàng)之前先抽取一下這個(gè)動(dòng)態(tài)的值,所以我們?cè)黾恿艘粋€(gè)抽取項(xiàng)的名字叫做skuid,在attachedUrl中的調(diào)用方法為{skuid},真實(shí)請(qǐng)求時(shí),該項(xiàng)就會(huì)被自動(dòng)替換成我們上一個(gè)skuid抽取項(xiàng)抽取到的值。接著,由于我們獲取到的是json返回,因此我們抽取的方式應(yīng)該是通過(guò)jsonpath,最后,寫(xiě)一個(gè)抽取規(guī)則既可,jsonpath比xpath更加簡(jiǎn)單,相信大家一看就懂了。
好了,弄了這么多,完整的代碼如下:
var configs = { domains: ["www.showjoy.com","list.showjoy.com","item.showjoy.com"], scanUrls: ["http://list.showjoy.com/search/?q=cateIds%3A1,cateName%3A%E9%9D%A2%E8%86%9C"], contentUrlRegexes: ["http://item.showjoy.com/sku/d+.html"], helperUrlRegexes: ["http://list.showjoy.com/search/?q=cateIds%3A1,cateName%3A%E9%9D%A2%E8%86%9C(&page=d+)?"],//可留空 fields: [ { // 第一個(gè)抽取項(xiàng) name: "title", selector: "http://h3[contains(@class,"choose-hd")]",//默認(rèn)使用XPath required: true //是否不能為空 }, { // 第二個(gè)抽取項(xiàng) name: "comment", selector: "http://div[contains(@class,"dtabs-hd")]/ul/li[2]",//使用正則的抽取規(guī)則 required: false //是否不能為空 }, { // 第三個(gè)抽取項(xiàng) name: "sales", selector: "http://div[contains(@class,"dtabs-hd")]/ul/li[3]",//使用正則的抽取規(guī)則 required: false //是否不能為空 }, { name: "skuid", selector: "http://input[@id="J_UItemId"]/@value", }, { name: "price", sourceType: SourceType.AttachedUrl, attachedUrl: "http://item.showjoy.com/product/getPrice?skuId={skuid}", selectorType: SelectorType.JsonPath, selector: "$.data.price", } ] }; configs.onProcessHelperUrl = function(url, content, site){ if(!content.indexOf("無(wú)匹配商品")){ //如果沒(méi)有到最后一頁(yè),則將頁(yè)數(shù)加1 var currentPage = parseInt(url.substring(url.indexOf("&page=") + 6)); var page = currentPage + 1; var nextUrl = url.replace("&page=" + currentPage, "&page=" + page); site.addUrl(nextUrl); } return true; } var crawler = new Crawler(configs); crawler.start();
終于搞定了,我們趕緊測(cè)試一下爬取的結(jié)果吧:
欣賞自己艱苦的勞動(dòng)成果是不是很有成就感,不過(guò)現(xiàn)在的爬取結(jié)果依然有些美中不足,評(píng)論數(shù)和銷(xiāo)售額拿到的都是一個(gè)完整的句子,而我們希望得到的是具體的數(shù)字,這個(gè)怎么操作呢?這個(gè)其實(shí)就是一個(gè)字段抽取到之后的進(jìn)一步處理,框架中給我們提供了一個(gè)回調(diào)函數(shù)為:
afterExtractField(fieldName, data)
函數(shù)會(huì)將抽取名和抽取到的數(shù)據(jù)傳進(jìn)來(lái),我們只需要通過(guò)js的字符串處理函數(shù)對(duì)數(shù)據(jù)進(jìn)行進(jìn)一步加工既可,直接上完整的修改過(guò)的代碼:
var configs = { domains: ["www.showjoy.com","list.showjoy.com","item.showjoy.com"], scanUrls: ["http://list.showjoy.com/search/?q=cateIds%3A1,cateName%3A%E9%9D%A2%E8%86%9C"], contentUrlRegexes: ["http://item.showjoy.com/sku/d+.html"], helperUrlRegexes: ["http://list.showjoy.com/search/?q=cateIds%3A1,cateName%3A%E9%9D%A2%E8%86%9C(&page=d+)?"],//可留空 fields: [ { // 第一個(gè)抽取項(xiàng) name: "title", selector: "http://h3[contains(@class,"choose-hd")]",//默認(rèn)使用XPath required: true //是否不能為空 }, { // 第二個(gè)抽取項(xiàng) name: "comment", selector: "http://div[contains(@class,"dtabs-hd")]/ul/li[2]",//使用正則的抽取規(guī)則 required: false //是否不能為空 }, { // 第三個(gè)抽取項(xiàng) name: "sales", selector: "http://div[contains(@class,"dtabs-hd")]/ul/li[3]",//使用正則的抽取規(guī)則 required: false //是否不能為空 }, { name: "skuid", selector: "http://input[@id="J_UItemId"]/@value", }, { name: "price", sourceType: SourceType.AttachedUrl, attachedUrl: "http://item.showjoy.com/product/getPrice?skuId={skuid}", selectorType: SelectorType.JsonPath, selector: "$.data.price", } ] }; configs.onProcessHelperUrl = function(url, content, site){ if(!content.indexOf("無(wú)匹配商品")){ //如果沒(méi)有到最后一頁(yè),則將頁(yè)數(shù)加1 var currentPage = parseInt(url.substring(url.indexOf("&page=") + 6)); var page = currentPage + 1; var nextUrl = url.replace("&page=" + currentPage, "&page=" + page); site.addUrl(nextUrl); } return true; } configs.afterExtractField = function(fieldName, data){ if(fieldName == "comment" || fieldName == "sales"){ var regex = /.*((d+)).*/; return (data.match(regex))[1]; } return data; } var crawler = new Crawler(configs); crawler.start();
我們判斷了如果是comment和sales抽取項(xiàng)時(shí),通過(guò)正則直接匹配到括號(hào)里的數(shù)字,這里注意,網(wǎng)頁(yè)上的括號(hào)本來(lái)是全角的括號(hào),所以千萬(wàn)不要寫(xiě)錯(cuò)了。
這次終于可以開(kāi)心的看著自己的爬蟲(chóng)數(shù)據(jù)結(jié)果了:
對(duì)爬蟲(chóng)感興趣的童鞋可以加qq群討論:342953471。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/37942.html
摘要:系列教程手把手教你寫(xiě)電商爬蟲(chóng)第一課找個(gè)軟柿子捏捏手把手教你寫(xiě)電商爬蟲(chóng)第二課實(shí)戰(zhàn)尚妝網(wǎng)分頁(yè)商品采集爬蟲(chóng)看完兩篇,相信大家已經(jīng)從開(kāi)始的小菜鳥(niǎo)晉升為中級(jí)菜鳥(niǎo)了,好了,那我們就繼續(xù)我們的爬蟲(chóng)課程。 系列教程: 手把手教你寫(xiě)電商爬蟲(chóng)-第一課 找個(gè)軟柿子捏捏手把手教你寫(xiě)電商爬蟲(chóng)-第二課 實(shí)戰(zhàn)尚妝網(wǎng)分頁(yè)商品采集爬蟲(chóng) 看完兩篇,相信大家已經(jīng)從開(kāi)始的小菜鳥(niǎo)晉升為中級(jí)菜鳥(niǎo)了,好了,那我們就繼續(xù)我們的爬蟲(chóng)課...
摘要:剩下的同學(xué),我們繼續(xù)了可以看出,作為一個(gè)完善的電商網(wǎng)站,尚妝網(wǎng)有著普通電商網(wǎng)站所擁有的主要的元素,包括分類(lèi),分頁(yè),主題等等。 系列教程 手把手教你寫(xiě)電商爬蟲(chóng)-第一課 找個(gè)軟柿子捏捏 如果沒(méi)有看過(guò)第一課的朋友,請(qǐng)先移步第一課,第一課講了一些基礎(chǔ)性的東西,通過(guò)軟柿子切糕王子這個(gè)電商網(wǎng)站好好的練了一次手,相信大家都應(yīng)該對(duì)寫(xiě)爬蟲(chóng)的流程有了一個(gè)大概的了解,那么這課咱們就話不多說(shuō),正式上戰(zhàn)場(chǎng),對(duì)壘...
摘要:剩下的同學(xué),我們繼續(xù)了可以看出,作為一個(gè)完善的電商網(wǎng)站,尚妝網(wǎng)有著普通電商網(wǎng)站所擁有的主要的元素,包括分類(lèi),分頁(yè),主題等等。 系列教程 手把手教你寫(xiě)電商爬蟲(chóng)-第一課 找個(gè)軟柿子捏捏 如果沒(méi)有看過(guò)第一課的朋友,請(qǐng)先移步第一課,第一課講了一些基礎(chǔ)性的東西,通過(guò)軟柿子切糕王子這個(gè)電商網(wǎng)站好好的練了一次手,相信大家都應(yīng)該對(duì)寫(xiě)爬蟲(chóng)的流程有了一個(gè)大概的了解,那么這課咱們就話不多說(shuō),正式上戰(zhàn)場(chǎng),對(duì)壘...
摘要:老規(guī)矩,爬之前首先感謝淘寶公布出這么多有價(jià)值的數(shù)據(jù),才讓我們這些爬蟲(chóng)們有東西可以搜集啊,不過(guò)淘寶就不用我來(lái)安利了廣大剁手黨相信睡覺(jué)的時(shí)候都能把網(wǎng)址打出來(lái)吧。 系列教程: 手把手教你寫(xiě)電商爬蟲(chóng)-第一課 找個(gè)軟柿子捏捏 手把手教你寫(xiě)電商爬蟲(chóng)-第二課 實(shí)戰(zhàn)尚妝網(wǎng)分頁(yè)商品采集爬蟲(chóng) 手把手教你寫(xiě)電商爬蟲(chóng)-第三課 實(shí)戰(zhàn)尚妝網(wǎng)AJAX請(qǐng)求處理和內(nèi)容提取 都已經(jīng)三節(jié)課了,大家活動(dòng)活動(dòng)手腳,咱們開(kāi)始一場(chǎng)...
摘要:老規(guī)矩,爬之前首先感謝淘寶公布出這么多有價(jià)值的數(shù)據(jù),才讓我們這些爬蟲(chóng)們有東西可以搜集啊,不過(guò)淘寶就不用我來(lái)安利了廣大剁手黨相信睡覺(jué)的時(shí)候都能把網(wǎng)址打出來(lái)吧。 系列教程: 手把手教你寫(xiě)電商爬蟲(chóng)-第一課 找個(gè)軟柿子捏捏 手把手教你寫(xiě)電商爬蟲(chóng)-第二課 實(shí)戰(zhàn)尚妝網(wǎng)分頁(yè)商品采集爬蟲(chóng) 手把手教你寫(xiě)電商爬蟲(chóng)-第三課 實(shí)戰(zhàn)尚妝網(wǎng)AJAX請(qǐng)求處理和內(nèi)容提取 都已經(jīng)三節(jié)課了,大家活動(dòng)活動(dòng)手腳,咱們開(kāi)始一場(chǎng)...
閱讀 2852·2023-04-25 18:58
閱讀 981·2021-11-25 09:43
閱讀 1216·2021-10-25 09:46
閱讀 3504·2021-09-09 11:40
閱讀 1698·2021-08-05 09:59
閱讀 874·2019-08-29 15:07
閱讀 964·2019-08-29 12:48
閱讀 704·2019-08-29 11:19