Selenium實(shí)戰(zhàn)——天貓?zhí)詫毦〇|買家秀

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-next
    2018111-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è)圖片比較多的商品吧。

    https://item.taobao.com/item.htm?spm=a219r.lm893.14.1.3b9cc350h7CJf8&id=561861021238&ns=1&abbucket=16

    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ā)了兩張一樣的)

  • 在本地文件夾中可以輕松查看:

2018111-shoe
  • 因?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-dikan
    2018111-hat
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容