Selenium实战——天猫淘宝京东买家秀

Selenium实战——天猫淘宝京东买家秀

源码地址:https://github.com/edisonleolhl/BuyersShow

1、起因

  • 作为一个关注什么值得买已久的人,作为一个微博都关注了好几个白菜君的人,在各大电商网站上薅羊毛那是再平常不过了。作为一个从来没看过商品的买家,商品评论里的买家秀自然是重点关注。

  • 然而有的商品,只钟意其中一种颜色,或者款式,也许这个款式很特别,买的人很少,即使在评论区选择“带图”评价,可能好几页才有一个买家秀,这无疑是非常耗时又耗力的。

  • 而且,商家有时候为了评价数量更多、更好看,新款的商品会和老款商品放在一起卖,选择款式的时候区分开,但是评价里却还有很多老款的,新款的寥寥无几,不禁想到:如果能一次性只看一种款式的买家秀就好了。

  • 作为一个Python爬虫的实践者,就琢磨着能不能写个自动化工具,告诉程序商品的url地址,然后在本地就会有所有的买家秀图片,并且是按款式区分的,于是,说干就干,总共用时一天,反正坑挺多的。。

2、步骤

  • 首先,访问这些评论,是不需要登录的,所以最开始我搞了挺久的cookies,后来发现根本不需要。。

  • selenium作为一个强大的自动化工具,几乎可以完全模拟浏览器的所有行为,抓取买家秀自然不在话下,如果你对selenium还不太了解,请看这篇文章:https://www.jianshu.com/p/c8ed978dd0ab

  • 先抓淘宝吧,进入商品页面后,先要跳转到评论部分,点击“累计评论”这个按钮就好了。注意了,先得把窗口最大化哦,

      driver.maximize_window()
    
    2018111-taobao
  • 用xpath语法来选择这个按钮吧,如何快速知道这个元素的xpath路径呢,推荐chrome浏览器安装xpath helper这个插件,打开插件,按住shift,把鼠标移动到元素上,框里自动出来xpath路径了。

      driver.find_element_by_xpath(".//*/a[@id='J_ReviewTabTrigger']").click() # 累计评论
    
    2018111-taobaoxpath
  • 点击“有图”

      driver.find_element_by_xpath(".//*/label/input[@id='reviews-t-val3']").send_keys(Keys.SPACE) # 有图
    
  • 接下来是得到所有图片,这个比较简单,因为所有买家秀图片都是在li这个标签里面,而且这个li标签的class='photo-item',所以xpath语法这样写就好了,最后会得到一个关于img_ele_list的列表:

      img_ele_list = driver.find_elements_by_xpath(".//*/li[@class='photo-item']/img")
    
  • 得到img_ele,调用img_ele_list[i].get_attribute('src'),即可得到图片的url,但是注意,这个时候图片只有40x40!因为这是小图,那大图怎么办,点开一个买家秀,查看大图,发现它们的url有个规律:

    • 40x40:

      2018111-40x40
    • 400x400:

      2018111-400x400
    • url那里除了40x40、400x400,其他完全一样,那其他图片是不是这样的呢?经过实践发现,把这里改成500x500,一样可以显示图片,图片大一号而已。通过总结得到,一般人都是用手机拍的照片,一般像素值肯定会大于400x400,于是这里直接替换成400x400即可,阿里已经存储了同一张图片的不同格式(虽然我觉得挺浪费空间的)。

      url = img_ele_list[i].get_attribute('src').replace('40x40', '400x400')
      
  • 好,图片下载完了,如果直接下载到本地,文件名肯定是乱七八糟的,这与我们“想要按款式分开买家秀”的初衷不符了,在存储图片的时候,应该知道这个图片是哪个款式,于是,我们需要找到这个图片元素所在的那个评论用户所买的款式。

    2018111-yuanma
  • 根据xpath语法,我们得到了img_ele,需要往上找3级父节点,再找弟弟,再找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 = 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 ('\\', '--')  # 款式要作为文件名的,所以不要/和\\
    
  • 从上图可以看到,同时也可以找到买家秀对应的用户评论,这里直接给出xpath语法:

      c = img_ele.find_element_by_xpath(".//../../../preceding-sibling::div[1]").text.replace ('/', '-').replace ('\\', '--')
    
  • 好的,一个完整的图片以及信息找到了,要遍历这一页的所有买家秀,怎么做呢?

  • 前文我们得到了img_ele_list,我们可以对其遍历,对每个img_ele,找到其对应的评论、日期、款式,各自加入到一个新的列表中,最后4个列表长度相等,代码如下:

    # 得到把该页的所有买家秀,存入列表中,并且创建另外三个列表,长度一样,
    # 分别存储每个买家秀的property和对应的用户发表的评论时间及内容
    # 我认为带买家秀的评论比较重要,最后在图片文件名中给出
    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]  # 得到日期时间
            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 ('\\', '--')  # 删掉日期时间,得到款式等信息
            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)

    # 四个列表长度一致,所以可以用同一个指针i来对四个列表同步遍历
    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个列表后,就开始下载这些图片了,图片名字举例如:

      颜色:卡其色  尺码:170-92A-M-2017年10月04日-1515648926.131808.jpg
    

翻页

  • 翻页从来都是一个重难点,但是掌握规律,是有迹可循的。看截图,评论有两页,第一页是这样的:

    2018111-next
    2018111-nextlast
  • 这里给出我的办法:找到pg-current的li,查它的弟弟元素,得到其文本值,如果是数字,则还没有到最后一页,如果不是数字,则到最后一页(即“下一页”),于是在这里用try...except捕捉一下,再所有代码之上套一个while循环,于是,代码如下:

      while True:
    
          # 得到把该页的所有买家秀,存入列表中,并且创建另外三个列表,长度一样,
          # 分别存储每个买家秀的property和对应的用户发表的评论时间及内容
          # 我认为带买家秀的评论比较重要,最后在图片文件名中给出
          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]  # 得到日期时间
                  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 ('\\', '--')  # 删掉日期时间,得到款式等信息
                  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)
    
          # 四个列表长度一致,所以可以用同一个指针i来对四个列表同步遍历
          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))
    
          # ---------------翻页---------------
          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]") # 淘宝的评论页码工具条,每个都是li标签
              if next.text.isdigit():
                  ActionChains(driver).click(next).perform()
                  time.sleep(1)
              else:
                  exit()
          except:
              print('only one page with img')
              exit()
    

3、结果

  • 在项目文件夹下,运行items.py,提示输入url,复制你在浏览器地址栏中的url,粘贴到命令行上(我用的是Pycharm IDE,最后要加个空格,防止IDE自动打开url),按下回车即可,这里找个图片比较多的商品吧。

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

    2018111-pycharmrun
  • 单个输出是这样的:

      A new img!!! PROPERTY = 颜色分类:米灰色厚绒  尺码:38, DATETIME = 2017年12月27日
      , COMMENT = 包装特别好,大盒子套小盒子,高大上,鞋特别暖和,毛毛特别多特别软,鞋底也厚,走路软软的,哈哈非常喜欢,都说好看,尺码也特准,超级喜欢
      , DOWALOADING url = https://img.alicdn.com/imgextra/i2/0/TB2wrG1klTH8KJjy0FiXXcRsXXa_!!0-rate.jpg_400x400.jpg
    
  • 因为一个买家可能有多个买家秀图片,还记得上文说的4个列表长度一致吗?好几个图片对应的款式、日期、评论,都是一样的,所以看起来命令行中会有重复的,但是url绝对是不一样的(即都是不同的买家秀,除非买家发表评论的时候手抖发了两张一样的)

  • 在本地文件夹中可以轻松查看:

2018111-shoe
  • 因为图片文件名开头是按款式区分的,所以文件夹中“按名称排序”即可把同款商品放在一起浏览,简单方便。

4、其他电商

天猫

  • 注意天猫和淘宝是两套不同的网页模版,所以还得重新设计xpath语法,主要有这几点需要更改的:

    • 各种xpath

    • 翻页操作(详情参考github上源码的注释)

京东

  • 京东的带图评价其实挺方便的,但是还是不能按款式浏览。

    2018111-jd
  • 对于jd而言,得到图片后,查询对应评价、日期、款式其实挺简单的,因为像上图一样,一个页面只有一个评论、日期、款式,很好处理,具体看源码即可。

  • 翻页操作,也是直接点下一个,就不详细叙述了。

5、后记

  • 小工具真的特别特别实用,才写了每两天,就用了好几次了(虽然都是些白菜),但是真的特别方便,买家秀才是反映商品的有效途径。

    2018111-dikan
    2018111-hat
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容