摘要:系列教程手把手教你寫電商爬蟲第一課找個(gè)軟柿子捏捏手把手教你寫電商爬蟲第二課實(shí)戰(zhàn)尚妝網(wǎng)分頁商品采集爬蟲看完兩篇,相信大家已經(jīng)從開始的小菜鳥晉升為中級(jí)菜鳥了,好了,那我們就繼續(xù)我們的爬蟲課程。
系列教程:
手把手教你寫電商爬蟲-第一課 找個(gè)軟柿子捏捏
手把手教你寫電商爬蟲-第二課 實(shí)戰(zhàn)尚妝網(wǎng)分頁商品采集爬蟲
看完兩篇,相信大家已經(jīng)從開始的小菜鳥晉升為中級(jí)菜鳥了,好了,那我們就繼續(xù)我們的爬蟲課程。
上一課呢一定是因?yàn)閷?duì)手太強(qiáng),導(dǎo)致我們并沒有完整的完成尚妝網(wǎng)的爬蟲。
吭吭~,我們這一課繼續(xù),爭取徹底搞定尚妝網(wǎng),不留任何遺憾。
我們先回顧一下,上一課主要遺留了兩個(gè)問題,兩個(gè)問題都和ajax有關(guān)。
1、由于是ajax加載下一頁,導(dǎo)致下一頁url并不會(huì)被系統(tǒng)自動(dòng)發(fā)現(xiàn)。
2、商品頁面的價(jià)格是通過ajax加載的,我們直接從網(wǎng)頁中獲取不到信息本身。
好了,我們先解決第一個(gè)問題:
第一個(gè)問題實(shí)際上是一個(gè)爬蟲中比較常見的問題,即url的發(fā)現(xiàn),默認(rèn)情況下,URL的發(fā)現(xiàn)是神箭手云爬蟲框架自動(dòng)處理的,但是如果在ajax的情況下,框架則無從發(fā)現(xiàn)url,這個(gè)時(shí)候就需要我們自己手動(dòng)處理url的發(fā)現(xiàn),這里,神箭手給我們提供了一個(gè)很方便的回調(diào)函數(shù)讓我們來自己處理url的發(fā)現(xiàn):
onProcessHelperUrl(url, content, site)
這個(gè)回調(diào)函數(shù)有兩個(gè)參數(shù),分別是當(dāng)前處理的頁面對(duì)象和整個(gè)爬取站的對(duì)象,我們可以通過獲取頁面對(duì)象的內(nèi)容來分析是否有我們需要的新一頁的url,通過site.addUrl()方法加入到url隊(duì)列中既可。這里我們可以看到,當(dāng)超出頁數(shù)的時(shí)候,尚妝網(wǎng)會(huì)給我們返回一個(gè)這樣的頁面,我們就知道頁數(shù)超過了,不需要在加入新的頁url:
這個(gè)頁面我們很好判斷,只需要看內(nèi)容中是否有"無匹配商品"關(guān)鍵字既可。
這里我們需要一些基礎(chǔ)的js能力,代碼如下:
configs.onProcessHelperUrl = function(url, content, site){ if(!content.indexOf("無匹配商品")){ //如果沒有到最后一頁,則將頁數(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); } }
原理很簡單,如果內(nèi)容中沒有無匹配商品這個(gè)關(guān)鍵詞的時(shí)候,則把當(dāng)前頁面的下一頁加入的待爬隊(duì)列中。
好了,ajax分頁問題徹底解決,下面來看這個(gè)最棘手的ajax內(nèi)容加載的問題,也就是如何獲取到商品頁面中的價(jià)格信息
首先,遇到這類問題,我們通常有兩個(gè)思路:
1、通過js引擎將整個(gè)頁面渲染出來之后,在去做內(nèi)容抽取,這個(gè)方案對(duì)于一些復(fù)雜js頁面是唯一解決方案,用神箭手來處理也很簡單,不過由于需要執(zhí)行js,導(dǎo)致抓取速度很慢,不到不得已情況,我們先不使用這個(gè)核武器
2、通過剛剛處理分頁的經(jīng)驗(yàn),我們可以預(yù)先分析ajax請(qǐng)求,然后將這一步多出來的請(qǐng)求和原來的頁面請(qǐng)求做一個(gè)關(guān)聯(lián)。這種方案適合比較簡單的js頁面中。
OK,介紹完思路,根據(jù)經(jīng)驗(yàn),我們感覺尚妝網(wǎng)的ajax加載并沒有十分復(fù)雜,所以我們選擇方案二來處理這種ajax頁面加載。
同樣的,首頁我們通過chrome開發(fā)者工具,抓取到這個(gè)ajax請(qǐng)求,這里教大家一個(gè)小竅門,開發(fā)者工具中,可以篩選請(qǐng)求對(duì)象未xhr,這種就是異步請(qǐng)求,我們就很容易發(fā)現(xiàn)我們的嫌疑url:
http://item.showjoy.com/product/getPrice?skuId=22912
我們?cè)陧撁嬷姓乙幌逻@個(gè)22912怎么提取最方便,我們很快就發(fā)現(xiàn)了一個(gè)標(biāo)簽:
這個(gè)標(biāo)簽很干凈,獲取的xpath也很簡單:
//input[@id="J_UItemId"]/@value
這樣就好辦了,我們?cè)倏聪逻@個(gè)頁面請(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}
可以看出來,是一個(gè)典型的json對(duì)象,這個(gè)就好辦了,神箭手中給我們提供了通過jsonpath提取內(nèi)容的方式,可以很簡單的提取到價(jià)格對(duì)象,即price對(duì)應(yīng)的值。
那最后我們?cè)趺床拍荜P(guān)聯(lián)這個(gè)請(qǐng)求呢?這里也是框架中提供的一個(gè)方案,叫做attachedUrl,專門用來解決關(guān)聯(lián)請(qǐng)求的請(qǐng)求的問題,也就是某一個(gè)字段的值可以通過一個(gè)關(guān)聯(lián)請(qǐng)求的內(nèi)容中抽取出來。語法我就不介紹了,直接上代碼吧:
{ 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", }
簡單介紹一下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)該是通過jsonpath,最后,寫一個(gè)抽取規(guī)則既可,jsonpath比xpath更加簡單,相信大家一看就懂了。
好了,弄了這么多,完整的代碼如下:
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("無匹配商品")){ //如果沒有到最后一頁,則將頁數(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)成果是不是很有成就感,不過現(xiàn)在的爬取結(jié)果依然有些美中不足,評(píng)論數(shù)和銷售額拿到的都是一個(gè)完整的句子,而我們希望得到的是具體的數(shù)字,這個(gè)怎么操作呢?這個(gè)其實(shí)就是一個(gè)字段抽取到之后的進(jìn)一步處理,框架中給我們提供了一個(gè)回調(diào)函數(shù)為:
afterExtractField(fieldName, data)
函數(shù)會(huì)將抽取名和抽取到的數(shù)據(jù)傳進(jìn)來,我們只需要通過js的字符串處理函數(shù)對(duì)數(shù)據(jù)進(jìn)行進(jì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("無匹配商品")){ //如果沒有到最后一頁,則將頁數(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í),通過正則直接匹配到括號(hào)里的數(shù)字,這里注意,網(wǎng)頁上的括號(hào)本來是全角的括號(hào),所以千萬不要寫錯(cuò)了。
這次終于可以開心的看著自己的爬蟲數(shù)據(jù)結(jié)果了:
對(duì)爬蟲感興趣的童鞋可以加qq群討論:342953471。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/37942.html
摘要:系列教程手把手教你寫電商爬蟲第一課找個(gè)軟柿子捏捏手把手教你寫電商爬蟲第二課實(shí)戰(zhàn)尚妝網(wǎng)分頁商品采集爬蟲看完兩篇,相信大家已經(jīng)從開始的小菜鳥晉升為中級(jí)菜鳥了,好了,那我們就繼續(xù)我們的爬蟲課程。 系列教程: 手把手教你寫電商爬蟲-第一課 找個(gè)軟柿子捏捏手把手教你寫電商爬蟲-第二課 實(shí)戰(zhàn)尚妝網(wǎng)分頁商品采集爬蟲 看完兩篇,相信大家已經(jīng)從開始的小菜鳥晉升為中級(jí)菜鳥了,好了,那我們就繼續(xù)我們的爬蟲課...
摘要:剩下的同學(xué),我們繼續(xù)了可以看出,作為一個(gè)完善的電商網(wǎng)站,尚妝網(wǎng)有著普通電商網(wǎng)站所擁有的主要的元素,包括分類,分頁,主題等等。 系列教程 手把手教你寫電商爬蟲-第一課 找個(gè)軟柿子捏捏 如果沒有看過第一課的朋友,請(qǐng)先移步第一課,第一課講了一些基礎(chǔ)性的東西,通過軟柿子切糕王子這個(gè)電商網(wǎng)站好好的練了一次手,相信大家都應(yīng)該對(duì)寫爬蟲的流程有了一個(gè)大概的了解,那么這課咱們就話不多說,正式上戰(zhàn)場(chǎng),對(duì)壘...
摘要:剩下的同學(xué),我們繼續(xù)了可以看出,作為一個(gè)完善的電商網(wǎng)站,尚妝網(wǎng)有著普通電商網(wǎng)站所擁有的主要的元素,包括分類,分頁,主題等等。 系列教程 手把手教你寫電商爬蟲-第一課 找個(gè)軟柿子捏捏 如果沒有看過第一課的朋友,請(qǐng)先移步第一課,第一課講了一些基礎(chǔ)性的東西,通過軟柿子切糕王子這個(gè)電商網(wǎng)站好好的練了一次手,相信大家都應(yīng)該對(duì)寫爬蟲的流程有了一個(gè)大概的了解,那么這課咱們就話不多說,正式上戰(zhàn)場(chǎng),對(duì)壘...
摘要:老規(guī)矩,爬之前首先感謝淘寶公布出這么多有價(jià)值的數(shù)據(jù),才讓我們這些爬蟲們有東西可以搜集啊,不過淘寶就不用我來安利了廣大剁手黨相信睡覺的時(shí)候都能把網(wǎng)址打出來吧。 系列教程: 手把手教你寫電商爬蟲-第一課 找個(gè)軟柿子捏捏 手把手教你寫電商爬蟲-第二課 實(shí)戰(zhàn)尚妝網(wǎng)分頁商品采集爬蟲 手把手教你寫電商爬蟲-第三課 實(shí)戰(zhàn)尚妝網(wǎng)AJAX請(qǐng)求處理和內(nèi)容提取 都已經(jīng)三節(jié)課了,大家活動(dòng)活動(dòng)手腳,咱們開始一場(chǎng)...
摘要:老規(guī)矩,爬之前首先感謝淘寶公布出這么多有價(jià)值的數(shù)據(jù),才讓我們這些爬蟲們有東西可以搜集啊,不過淘寶就不用我來安利了廣大剁手黨相信睡覺的時(shí)候都能把網(wǎng)址打出來吧。 系列教程: 手把手教你寫電商爬蟲-第一課 找個(gè)軟柿子捏捏 手把手教你寫電商爬蟲-第二課 實(shí)戰(zhàn)尚妝網(wǎng)分頁商品采集爬蟲 手把手教你寫電商爬蟲-第三課 實(shí)戰(zhàn)尚妝網(wǎng)AJAX請(qǐng)求處理和內(nèi)容提取 都已經(jīng)三節(jié)課了,大家活動(dòng)活動(dòng)手腳,咱們開始一場(chǎng)...
閱讀 2948·2023-04-25 18:58
閱讀 1059·2021-11-25 09:43
閱讀 1273·2021-10-25 09:46
閱讀 3569·2021-09-09 11:40
閱讀 1808·2021-08-05 09:59
閱讀 935·2019-08-29 15:07
閱讀 1016·2019-08-29 12:48
閱讀 789·2019-08-29 11:19