Selenium實(shí)戰(zhàn)——天貓?zhí)詫毦〇|買家秀
源碼地址:https://github.com/edisonleolhl/BuyersShow
1、起因
作為一個(gè)關(guān)注什么值得買已久的人,作為一個(gè)微博都關(guān)注了好幾個(gè)白菜君的人,在各大電商網(wǎng)站上薅羊毛那是再平常不過了。作為一個(gè)從來沒看過商品的買家,商品評(píng)論里的買家秀自然是重點(diǎn)關(guān)注。
然而有的商品,只鐘意其中一種顏色,或者款式,也許這個(gè)款式很特別,買的人很少,即使在評(píng)論區(qū)選擇“帶圖”評(píng)價(jià),可能好幾頁(yè)才有一個(gè)買家秀,這無(wú)疑是非常耗時(shí)又耗力的。
而且,商家有時(shí)候?yàn)榱嗽u(píng)價(jià)數(shù)量更多、更好看,新款的商品會(huì)和老款商品放在一起賣,選擇款式的時(shí)候區(qū)分開,但是評(píng)價(jià)里卻還有很多老款的,新款的寥寥無(wú)幾,不禁想到:如果能一次性只看一種款式的買家秀就好了。
作為一個(gè)Python爬蟲的實(shí)踐者,就琢磨著能不能寫個(gè)自動(dòng)化工具,告訴程序商品的url地址,然后在本地就會(huì)有所有的買家秀圖片,并且是按款式區(qū)分的,于是,說干就干,總共用時(shí)一天,反正坑挺多的。。
2、步驟
首先,訪問這些評(píng)論,是不需要登錄的,所以最開始我搞了挺久的cookies,后來發(fā)現(xiàn)根本不需要。。
selenium作為一個(gè)強(qiáng)大的自動(dòng)化工具,幾乎可以完全模擬瀏覽器的所有行為,抓取買家秀自然不在話下,如果你對(duì)selenium還不太了解,請(qǐng)看這篇文章:http://www.itdecent.cn/p/c8ed978dd0ab
-
先抓淘寶吧,進(jìn)入商品頁(yè)面后,先要跳轉(zhuǎn)到評(píng)論部分,點(diǎn)擊“累計(jì)評(píng)論”這個(gè)按鈕就好了。注意了,先得把窗口最大化哦,
driver.maximize_window()2018111-taobao -
用xpath語(yǔ)法來選擇這個(gè)按鈕吧,如何快速知道這個(gè)元素的xpath路徑呢,推薦chrome瀏覽器安裝xpath helper這個(gè)插件,打開插件,按住shift,把鼠標(biāo)移動(dòng)到元素上,框里自動(dòng)出來xpath路徑了。
driver.find_element_by_xpath(".//*/a[@id='J_ReviewTabTrigger']").click() # 累計(jì)評(píng)論2018111-taobaoxpath -
點(diǎn)擊“有圖”
driver.find_element_by_xpath(".//*/label/input[@id='reviews-t-val3']").send_keys(Keys.SPACE) # 有圖 -
接下來是得到所有圖片,這個(gè)比較簡(jiǎn)單,因?yàn)樗匈I家秀圖片都是在li這個(gè)標(biāo)簽里面,而且這個(gè)li標(biāo)簽的class='photo-item',所以xpath語(yǔ)法這樣寫就好了,最后會(huì)得到一個(gè)關(guān)于img_ele_list的列表:
img_ele_list = driver.find_elements_by_xpath(".//*/li[@class='photo-item']/img") -
得到img_ele,調(diào)用img_ele_list[i].get_attribute('src'),即可得到圖片的url,但是注意,這個(gè)時(shí)候圖片只有40x40!因?yàn)檫@是小圖,那大圖怎么辦,點(diǎn)開一個(gè)買家秀,查看大圖,發(fā)現(xiàn)它們的url有個(gè)規(guī)律:
-
40x40:
2018111-40x40 -
400x400:
2018111-400x400 -
url那里除了40x40、400x400,其他完全一樣,那其他圖片是不是這樣的呢?經(jīng)過實(shí)踐發(fā)現(xiàn),把這里改成500x500,一樣可以顯示圖片,圖片大一號(hào)而已。通過總結(jié)得到,一般人都是用手機(jī)拍的照片,一般像素值肯定會(huì)大于400x400,于是這里直接替換成400x400即可,阿里已經(jīng)存儲(chǔ)了同一張圖片的不同格式(雖然我覺得挺浪費(fèi)空間的)。
url = img_ele_list[i].get_attribute('src').replace('40x40', '400x400')
-
-
好,圖片下載完了,如果直接下載到本地,文件名肯定是亂七八糟的,這與我們“想要按款式分開買家秀”的初衷不符了,在存儲(chǔ)圖片的時(shí)候,應(yīng)該知道這個(gè)圖片是哪個(gè)款式,于是,我們需要找到這個(gè)圖片元素所在的那個(gè)評(píng)論用戶所買的款式。
2018111-yuanma -
根據(jù)xpath語(yǔ)法,我們得到了img_ele,需要往上找3級(jí)父節(jié)點(diǎn),再找弟弟,再找class='tb-r-info'的div,
p = img_ele_list[i].find_element_by_xpath("./../../../following-sibling::div[1]/div[@class='tb-r-info']") -
但是得到的輸出是這樣的:
p = '2017年11月27日 10:06顏色分類:紅色 參考身高:130cm' -
這里用正則表達(dá)式,把日期和款式分開:
d = re.findall (r'^20[0-9][0-9].[0-1][0-9].[0-3][0-9].', p.text)[0] p = re.findall (r'(?<=[0-9][0-9]:[0-9][0-9]).+$', p.text)[0].replace ('/', '-').replace ('\\', '--') # 款式要作為文件名的,所以不要/和\\ -
從上圖可以看到,同時(shí)也可以找到買家秀對(duì)應(yīng)的用戶評(píng)論,這里直接給出xpath語(yǔ)法:
c = img_ele.find_element_by_xpath(".//../../../preceding-sibling::div[1]").text.replace ('/', '-').replace ('\\', '--') 好的,一個(gè)完整的圖片以及信息找到了,要遍歷這一頁(yè)的所有買家秀,怎么做呢?
前文我們得到了img_ele_list,我們可以對(duì)其遍歷,對(duì)每個(gè)img_ele,找到其對(duì)應(yīng)的評(píng)論、日期、款式,各自加入到一個(gè)新的列表中,最后4個(gè)列表長(zhǎng)度相等,代碼如下:
# 得到把該頁(yè)的所有買家秀,存入列表中,并且創(chuàng)建另外三個(gè)列表,長(zhǎng)度一樣,
# 分別存儲(chǔ)每個(gè)買家秀的property和對(duì)應(yīng)的用戶發(fā)表的評(píng)論時(shí)間及內(nèi)容
# 我認(rèn)為帶買家秀的評(píng)論比較重要,最后在圖片文件名中給出
img_ele_list = driver.find_elements_by_xpath(".//*/li[@class='photo-item']/img")
property_list = []
datetime_list = []
comment_list = []
p, d, c = '', '', ''
for img_ele in img_ele_list:
try:
p = img_ele.find_element_by_xpath("./../../../following-sibling::div[1]/div[@class='tb-r-info']") # p = '2017年11月27日 10:06顏色分類:紅色 參考身高:130cm'
d = re.findall (r'^20[0-9][0-9].[0-1][0-9].[0-3][0-9].', p.text)
if len(d) > 0:
d = d[0] # 得到日期時(shí)間
else:
d = ''
p = re.findall (r'(?<=[0-9][0-9]:[0-9][0-9]).+$', p.text)
if len(p) > 0:
p = p[0].replace ('/', '-').replace ('\\', '--') # 刪掉日期時(shí)間,得到款式等信息
else:
p = ''
c = img_ele.find_element_by_xpath(".//../../../preceding-sibling::div[1]").text.replace ('/', '-').replace ('\\', '--')
except Exception as e:
print("ERROR happens when getting corresponding property of img :::", e)
datetime_list.append (d)
property_list.append (p)
comment_list.append (c)
# 四個(gè)列表長(zhǎng)度一致,所以可以用同一個(gè)指針i來對(duì)四個(gè)列表同步遍歷
for i in range(len(img_ele_list)):
url = img_ele_list[i].get_attribute('src').replace('40x40', '400x400')
with open (path + '/' + property_list[i] + '-' + datetime_list[i] + '-' + str(time.time()) + '.jpg', 'wb+') as f_img:
try:
f_img.write (urllib.request.urlopen (url).read ())
except:
print("Img url illegal: " + url)
else:
print ("A new img!!! PROPERTY = %s, DATETIME = %s\n, COMMENT = %s\n, DOWALOADING url = %s"
%(property_list[i], datetime_list[i], comment_list[i], url))
-
可以看到,完成了4個(gè)列表后,就開始下載這些圖片了,圖片名字舉例如:
顏色:卡其色 尺碼:170-92A-M-2017年10月04日-1515648926.131808.jpg
翻頁(yè)
-
翻頁(yè)從來都是一個(gè)重難點(diǎn),但是掌握規(guī)律,是有跡可循的??唇貓D,評(píng)論有兩頁(yè),第一頁(yè)是這樣的:
2018111-next2018111-nextlast -
這里給出我的辦法:找到pg-current的li,查它的弟弟元素,得到其文本值,如果是數(shù)字,則還沒有到最后一頁(yè),如果不是數(shù)字,則到最后一頁(yè)(即“下一頁(yè)”),于是在這里用try...except捕捉一下,再所有代碼之上套一個(gè)while循環(huán),于是,代碼如下:
while True: # 得到把該頁(yè)的所有買家秀,存入列表中,并且創(chuàng)建另外三個(gè)列表,長(zhǎng)度一樣, # 分別存儲(chǔ)每個(gè)買家秀的property和對(duì)應(yīng)的用戶發(fā)表的評(píng)論時(shí)間及內(nèi)容 # 我認(rèn)為帶買家秀的評(píng)論比較重要,最后在圖片文件名中給出 img_ele_list = driver.find_elements_by_xpath(".//*/li[@class='photo-item']/img") property_list = [] datetime_list = [] comment_list = [] p, d, c = '', '', '' for img_ele in img_ele_list: try: p = img_ele.find_element_by_xpath("./../../../following-sibling::div[1]/div[@class='tb-r-info']") # p = '2017年11月27日 10:06顏色分類:紅色 參考身高:130cm' d = re.findall (r'^20[0-9][0-9].[0-1][0-9].[0-3][0-9].', p.text) if len(d) > 0: d = d[0] # 得到日期時(shí)間 else: d = '' p = re.findall (r'(?<=[0-9][0-9]:[0-9][0-9]).+$', p.text) if len(p) > 0: p = p[0].replace ('/', '-').replace ('\\', '--') # 刪掉日期時(shí)間,得到款式等信息 else: p = '' c = img_ele.find_element_by_xpath(".//../../../preceding-sibling::div[1]").text.replace ('/', '-').replace ('\\', '--') except Exception as e: print("ERROR happens when getting corresponding property of img :::", e) datetime_list.append (d) property_list.append (p) comment_list.append (c) # 四個(gè)列表長(zhǎng)度一致,所以可以用同一個(gè)指針i來對(duì)四個(gè)列表同步遍歷 for i in range(len(img_ele_list)): url = img_ele_list[i].get_attribute('src').replace('40x40', '400x400') with open (path + '/' + property_list[i] + '-' + datetime_list[i] + '-' + str(time.time()) + '.jpg', 'wb+') as f_img: try: f_img.write (urllib.request.urlopen (url).read ()) except: print("Img url illegal: " + url) else: print ("A new img!!! PROPERTY = %s, DATETIME = %s\n, COMMENT = %s\n, DOWALOADING url = %s" %(property_list[i], datetime_list[i], comment_list[i], url)) # ---------------翻頁(yè)--------------- driver.execute_script ("window.scrollBy(0,-100)") time.sleep(1) try: next = driver.find_element_by_xpath(".//*/ul/li[@class='pg-current']/./following-sibling::li[1]") # 淘寶的評(píng)論頁(yè)碼工具條,每個(gè)都是li標(biāo)簽 if next.text.isdigit(): ActionChains(driver).click(next).perform() time.sleep(1) else: exit() except: print('only one page with img') exit()
3、結(jié)果
-
在項(xiàng)目文件夾下,運(yùn)行items.py,提示輸入url,復(fù)制你在瀏覽器地址欄中的url,粘貼到命令行上(我用的是Pycharm IDE,最后要加個(gè)空格,防止IDE自動(dòng)打開url),按下回車即可,這里找個(gè)圖片比較多的商品吧。
2018111-pycharmrun -
單個(gè)輸出是這樣的:
A new img!!! PROPERTY = 顏色分類:米灰色厚絨 尺碼:38, DATETIME = 2017年12月27日 , COMMENT = 包裝特別好,大盒子套小盒子,高大上,鞋特別暖和,毛毛特別多特別軟,鞋底也厚,走路軟軟的,哈哈非常喜歡,都說好看,尺碼也特準(zhǔn),超級(jí)喜歡 , DOWALOADING url = https://img.alicdn.com/imgextra/i2/0/TB2wrG1klTH8KJjy0FiXXcRsXXa_!!0-rate.jpg_400x400.jpg 因?yàn)橐粋€(gè)買家可能有多個(gè)買家秀圖片,還記得上文說的4個(gè)列表長(zhǎng)度一致嗎?好幾個(gè)圖片對(duì)應(yīng)的款式、日期、評(píng)論,都是一樣的,所以看起來命令行中會(huì)有重復(fù)的,但是url絕對(duì)是不一樣的(即都是不同的買家秀,除非買家發(fā)表評(píng)論的時(shí)候手抖發(fā)了兩張一樣的)
在本地文件夾中可以輕松查看:

- 因?yàn)閳D片文件名開頭是按款式區(qū)分的,所以文件夾中“按名稱排序”即可把同款商品放在一起瀏覽,簡(jiǎn)單方便。
4、其他電商
天貓
-
注意天貓和淘寶是兩套不同的網(wǎng)頁(yè)模版,所以還得重新設(shè)計(jì)xpath語(yǔ)法,主要有這幾點(diǎn)需要更改的:
各種xpath
翻頁(yè)操作(詳情參考github上源碼的注釋)
京東
-
京東的帶圖評(píng)價(jià)其實(shí)挺方便的,但是還是不能按款式瀏覽。
2018111-jd 對(duì)于jd而言,得到圖片后,查詢對(duì)應(yīng)評(píng)價(jià)、日期、款式其實(shí)挺簡(jiǎn)單的,因?yàn)橄裆蠄D一樣,一個(gè)頁(yè)面只有一個(gè)評(píng)論、日期、款式,很好處理,具體看源碼即可。
翻頁(yè)操作,也是直接點(diǎn)下一個(gè),就不詳細(xì)敘述了。
5、后記
-
小工具真的特別特別實(shí)用,才寫了每?jī)商?,就用了好幾次了(雖然都是些白菜),但是真的特別方便,買家秀才是反映商品的有效途徑。
2018111-dikan2018111-hat










