廢話少說(shuō)
很慶幸暑假入了python的坑抵屿,也很慶幸選擇學(xué)習(xí)爬蟲(chóng)摹恰,因?yàn)橛胮ython真的可以用很少的代碼完成很多有趣的事情,爬蟲(chóng)便是其中之一硼婿。斷斷續(xù)續(xù)學(xué)爬蟲(chóng)有幾個(gè)月了锌半,現(xiàn)在我早已不滿足于最開(kāi)始單進(jìn)程,單IP寇漫,爬豆瓣刊殉,糗事百科這種純靜態(tài)請(qǐng)求的頁(yè)面,爬取這種動(dòng)態(tài)請(qǐng)求數(shù)據(jù)的其實(shí)更有意思州胳。因?yàn)槲易约焊杏X(jué)做爬蟲(chóng)有倆個(gè)地方很爽记焊,一個(gè)就是成功分析出了目標(biāo)網(wǎng)站請(qǐng)求數(shù)據(jù)的策略,另一個(gè)地方就是成功爬到數(shù)據(jù)的時(shí)候栓撞,看著數(shù)據(jù)一條條刷刷刷的保存到本地的時(shí)候是真的爽遍膜。
學(xué)習(xí)爬蟲(chóng)碗硬,一定要嘗試爬一爬電商平臺(tái)的數(shù)據(jù),一定要嘗試逐步提高自己的爬取數(shù)據(jù)量瓢颅,要不你還以為所有的網(wǎng)站那么容易爬呢恩尾!今天,我就來(lái)爬一爬速賣通(阿里的跨境電商平臺(tái))的用戶評(píng)論惜索。
正文
環(huán)境準(zhǔn)備
python 環(huán)境
request庫(kù) 用于發(fā)送http/https請(qǐng)求特笋,接收響應(yīng)
BeautifulSoup庫(kù) 用于解析網(wǎng)頁(yè)
上述環(huán)境只是因?yàn)椴┲髁?xí)慣了而已,不是爬蟲(chóng)最核心的東西巾兆,搞清楚數(shù)據(jù)是怎么請(qǐng)求的猎物,可以選用不同的語(yǔ)言和庫(kù)去實(shí)現(xiàn)。
分析評(píng)論數(shù)據(jù)請(qǐng)求策略
分析請(qǐng)求就是看看我們目標(biāo)數(shù)據(jù)是從哪個(gè)http請(qǐng)求請(qǐng)求過(guò)來(lái)的角塑。在速賣通我們隨便打開(kāi)一個(gè)產(chǎn)品頁(yè)蔫磨,如下圖
feedback肯定就是評(píng)論的意思,我們點(diǎn)擊評(píng)論圃伶,并右鍵進(jìn)入開(kāi)發(fā)者工具
從谷歌開(kāi)發(fā)者工具Elements選項(xiàng)我們可以看出評(píng)論在類.buyer-feedback這個(gè)dt元素里堤如。
嘗試1:我們從瀏覽器復(fù)制鏈接,然后用requests向該鏈接發(fā)出get請(qǐng)求
咦窒朋,評(píng)論明明在這個(gè)頁(yè)面搀罢,為什么請(qǐng)求成功卻取不到這些評(píng)論數(shù)據(jù)。
這就是動(dòng)態(tài)請(qǐng)求數(shù)據(jù)與靜態(tài)請(qǐng)求的區(qū)別侥猩,靜態(tài)請(qǐng)求數(shù)據(jù)一般都是服務(wù)器端渲染好的了榔至,你請(qǐng)求到的時(shí)候已經(jīng)填充了數(shù)據(jù),而動(dòng)態(tài)請(qǐng)求是欺劳,客戶端通過(guò)發(fā)送ajax請(qǐng)求唧取,將數(shù)據(jù)請(qǐng)求到前端,然后由前端來(lái)渲染的划提,即用js把數(shù)據(jù)插入html頁(yè)面中的枫弟,所以真正的數(shù)據(jù)是通過(guò)另一個(gè)請(qǐng)求得到的,所以現(xiàn)在的問(wèn)題就是要找到這個(gè)請(qǐng)求評(píng)論數(shù)據(jù)的地址鹏往。
重新刷新頁(yè)面淡诗,右鍵開(kāi)發(fā)者工具 進(jìn)入network選項(xiàng),如下圖
可以發(fā)現(xiàn)伊履,現(xiàn)在已經(jīng)有了160多個(gè)請(qǐng)求袜漩,所以在點(diǎn)擊feedback之前一定要先clear掉現(xiàn)在所有的請(qǐng)求,否則你一點(diǎn)feedback湾碎,會(huì)出現(xiàn)更多請(qǐng)求宙攻,就不好判斷是哪個(gè)請(qǐng)求請(qǐng)求得到了評(píng)論數(shù)據(jù)
clear掉之后,點(diǎn)擊feedback,會(huì)看到你在點(diǎn)了feedback之后出現(xiàn)的請(qǐng)求介褥,所以評(píng)論數(shù)據(jù)的請(qǐng)求地址一定在這些請(qǐng)求當(dāng)中
這時(shí)候你基本有倆個(gè)選擇座掘,如果請(qǐng)求數(shù)不多的話递惋,點(diǎn)擊每一個(gè)請(qǐng)求,看看是不是溢陪;如果請(qǐng)求還是比較多萍虽,你可以利用谷歌開(kāi)發(fā)者工具上邊的請(qǐng)求過(guò)濾器,默認(rèn)是顯示全部類型的請(qǐng)求形真,因?yàn)槟阋业氖窃u(píng)論數(shù)據(jù)杉编,那么肯定不是圖片,css,media,Font等類型咆霜,最有可能的是XHR邓馒,JS,Doc
XHR即通過(guò)ajax異步請(qǐng)求的數(shù)據(jù)蛾坯,JS即js文件光酣,這個(gè)也是有可能的,Doc即html文檔
然后我們分別點(diǎn)擊XHR脉课,JS救军,Doc,一個(gè)個(gè)試(這個(gè)沒(méi)好辦法倘零,只能一個(gè)個(gè)試唱遭,但是你經(jīng)驗(yàn)越豐富,你試出來(lái)的時(shí)間越短呈驶,比如你從請(qǐng)求鏈接里的某個(gè)英文單詞拷泽,就大概可以猜出)最終在XHR,JS里都沒(méi)有發(fā)現(xiàn)俐东,那么按照排除法,只能在DOC里邊的請(qǐng)求了订晌,doc下只有倆個(gè)請(qǐng)求虏辫,其中一個(gè)請(qǐng)求中還有productEvaluation等字眼,直接告訴我锈拨,沒(méi)問(wèn)題砌庄,就是它了。
選擇preview或者response,往下拉一拉奕枢,很快就發(fā)現(xiàn)了評(píng)論數(shù)據(jù)娄昆,果然不出我所料,正常人在這個(gè)時(shí)候是有點(diǎn)爽的缝彬。
然后萌焰,我們來(lái)看看請(qǐng)求信息,選擇Headers
然后谷浅,我們模仿該請(qǐng)求來(lái)進(jìn)行第二次嘗試
嘗試2:我們直接從瀏覽器復(fù)制請(qǐng)求頭扒俯,連cookie一起復(fù)制
requests.get(url,headers=headers) 帶header請(qǐng)求發(fā)送get請(qǐng)求
可以發(fā)現(xiàn)奶卓,我們已經(jīng)正確取到了評(píng)論數(shù)據(jù),正常人這個(gè)時(shí)候應(yīng)該感覺(jué)更爽才對(duì)撼玄。
既然評(píng)論的請(qǐng)求地址搞清楚了夺姑,那么接下來(lái)考慮的是增大數(shù)據(jù)量爬取,看看會(huì)不會(huì)遇到什么問(wèn)題掌猛,因?yàn)樵u(píng)論有很多頁(yè)盏浙,所以我們很自然的想到可以考慮按頁(yè)數(shù)爬取全部的數(shù)據(jù),但是就在我打算寫(xiě)代碼的時(shí)候荔茬,我才突然發(fā)現(xiàn)我不知道怎么寫(xiě)!為什么废膘,因?yàn)槲彝蝗话l(fā)現(xiàn)剛才這個(gè)請(qǐng)求里沒(méi)有任何有關(guān)頁(yè)數(shù)的信息!
不過(guò)兔院,沒(méi)關(guān)系殖卑,這個(gè)辦法很好解決,因?yàn)轫?yè)面上是有分頁(yè)按鈕的坊萝,所以我們點(diǎn)擊第二頁(yè)孵稽,看看第二頁(yè)數(shù)據(jù)是怎么請(qǐng)求來(lái)的
還是按照之前的辦法,先clear掉之前的請(qǐng)求十偶,然后點(diǎn)擊第二頁(yè)菩鲜,觀察有哪些新的請(qǐng)求出現(xiàn),這個(gè)過(guò)程和之前類似惦积,我們很快就找到這個(gè)第二頁(yè)數(shù)據(jù)的請(qǐng)求地址
這個(gè)請(qǐng)求是POST請(qǐng)求接校,然后我分析提交的數(shù)據(jù),發(fā)現(xiàn)里邊有一個(gè)key是page狮崩,值是2蛛勉,那么這個(gè)page肯定是用來(lái)控制分頁(yè),所以其實(shí)這個(gè)接口才是真正的數(shù)據(jù)請(qǐng)求接口睦柴,可以根據(jù)不同的產(chǎn)品ID诽凌,賣家ID,頁(yè)數(shù)等信息獲取評(píng)論數(shù)據(jù)坦敌。到底是不是侣诵,我們繼續(xù)測(cè)試,同樣復(fù)制請(qǐng)求頭狱窘,和請(qǐng)求數(shù)據(jù)杜顺,cookie也要正確復(fù)制,否則得不到數(shù)據(jù)
嘗試3
requests.post(url,headers=headers,data=data) 可以帶請(qǐng)求頭和數(shù)據(jù)發(fā)出請(qǐng)求
可以發(fā)現(xiàn)蘸炸,成功獲取到了數(shù)據(jù)躬络,至此,我找到了數(shù)據(jù)請(qǐng)求地址搭儒,但是接下來(lái)還有一個(gè)最復(fù)雜的問(wèn)題洗鸵。
我隨便換一個(gè)產(chǎn)品ID越锈,甚至讓它為空,會(huì)發(fā)現(xiàn)請(qǐng)求到的數(shù)據(jù)還是原來(lái)的數(shù)據(jù)膘滨,如下圖
我們繼續(xù)觀察post的數(shù)據(jù)
會(huì)注意到有一個(gè)_csrf_token:xz4r263hT4WbCYfPCtSbq3 這個(gè)值甘凭,我猜肯定這個(gè)值是根據(jù)產(chǎn)品ID等信息變化的,也就是只有這個(gè)token對(duì)了火邓,才可以拿到數(shù)據(jù)丹弱。(別問(wèn)我為什么可以猜到,直覺(jué))
我們改一下這個(gè)token值
數(shù)據(jù)立刻就請(qǐng)求不到了2伞6愀臁!
搞了這么多纤勒,如果不能正確獲取token,前邊的分析都意義不大坯苹,總不能每次換一個(gè)產(chǎn)品,就手動(dòng)去瀏覽器里手動(dòng)復(fù)制token吧摇天。
那么這個(gè)token是怎么來(lái)的呢粹湃?
經(jīng)過(guò)我一天的摸索(這個(gè)我真心沒(méi)什么技巧,有的是服務(wù)器端生成的泉坐,有的是通過(guò)js執(zhí)行腳本生成的)为鳄,我終于發(fā)現(xiàn)了端倪。
還記不記得我們第一次嘗試腕让,即第一頁(yè)的評(píng)論是通過(guò)GET請(qǐng)求得到的孤钦,其實(shí)那個(gè)頁(yè)面除了請(qǐng)求第一頁(yè)評(píng)論外,還拿到了這個(gè)token值纯丸,如圖
md,藏的可真深吶F巍!觉鼻!
結(jié)論
所以最終請(qǐng)求策略就是
先根據(jù)productid,ownerMemberid,companyId構(gòu)造一個(gè)url俊扭,如下
url1=https://feedback.aliexpress.com/display/productEvaluation.htm?productId=32466567934&ownerMemberId=223275770&companyId=232994171&memberType=seller&startValidDate=&i18n=true
向這個(gè)url發(fā)送get請(qǐng)求,取到token值滑凉,同時(shí)保存cookie
然后帶著這個(gè)cookie统扳,以及token和其它數(shù)據(jù)向
url2=https://feedback.aliexpress.com/display/productEvaluation.htm
post數(shù)據(jù)喘帚,就ok了
基于python requests庫(kù)的 偽代碼
session=requests.Session() #用session是為了保存cookie
res=session.get(url1,header=header)
# 獲取token
token=get_token(res)
data={
...
'_csrf_token':token
}
comment=session.post(url2,headers=headers,data=data)
# 解析評(píng)論數(shù)據(jù)
data_list=parseComment(comment)
# 保存評(píng)論數(shù)據(jù)
store_data(data_list)
最后
到此畅姊,我們基本已經(jīng)搞清楚了速賣通評(píng)論的請(qǐng)求策略,在下一篇文章中吹由,我們開(kāi)始采用代理IP以及多線程來(lái)編寫(xiě)最終代碼若未。