爬取天猫国际、京东全球购、淘宝全球购的商品数据

公司内部mini项目–智慧选品

“智慧选品”项目主要是方便采购人员了解其他竞品平台的商品数据,将其他平台上卖的特别好的商品数据展示给采购人员,方便他们去采购商品,扩大公司自己的商品,所以就需要爬取其他平台的数据,本着需求出发,这里主要爬取天猫国际、京东全球购、淘宝全球购的商品属性数据,包括标题、品牌、价格、销量、评论数、收藏数、好评数等等,再利用推荐算法对数据排序。

需要解决的问题

  • 商品数据获取
  • 新品识别
  • 推荐算法

备注说明:
1、首先商品数据获取,其实京东全球购的数据获取不到销量,而且评论数也不是准确数字,这里只尽可能的采集数据,实在没有的商品属性也没办法。
2、新品识别其实是一个重点,因为你需要把其他平台中不存在我们商品数据的商品找出来,而且要精细到规格,这里就比较难受,因为像口红这样的商品,可能颜色就有10多个,要找出不存在我们商品数据中但在其他平台上的商品,难度较大,这里有很多问题,目前讨论出来的方法是,利用商品标题和商品一些属性做相似度匹配,这准确率实际效果不高。
3、推荐算法这里比较简单,后面单独开一篇博客讲解。

数据获取

这里使用的技术都是一样的,我先讲解利用什么技术手段来获取数据,其实目前获取数据手段也较多:

  • 直接利用http去请求访问电商商品数据,这里直接请求,速度较快,但是问题也是最多的,因为电商AJAX请求,这些数据是在页面上动态加载的,如果你只是简单的访问商品url,很多ajax请求数据是获取不到的,这些属性比如:价格、评论等等,所以你还必须去了解它的网页js脚本,要自己去分析页面的js运行情况,再通过访问js脚本来获取这些数据,这些数据也叫动态数据。另外,http请求较快,如果电商平台有反爬虫机制,很容易就会被限制访问,后面会统一讲解一下反爬机制。
  • selenium实现模拟人的行为来访问数据,这里所谓的模拟人的行为其实是启动一个新的浏览器窗口,然后利用selenium工具的一些接口来实现模拟用户的鼠标移动和点击,以及键盘的输入等功能,它是自动化测试的一个工具,功能非常的强大,因为是运行一个浏览器,所以它访问某个页面的时候可以获取页面静态数据和动态数据,不需要自己去了解页面js是怎么回事的,而且通过一个浏览器,它能自带“User-Agent ”以及相应的“Cookie”,当然它的缺点就是占用内存大,cpu使用高,毕竟开启了一个应用。
  • 方法已将讲解OK了,我的目的是尽快爬取到数据,所以我选择了第二种方法,后面也觉得这种方法是真的简单,所以接下来就会讲解此方法如何获取到三个电商平台的数据。
    pom引用

    <dependency>
            <groupId>org.seleniumhq.seleniumgroupId>
            <artifactId>selenium-serverartifactId>
            <version>2.53.0version>
     dependency>

    京东数据

    1、采集首页
    这个采集首页的意思就是开始采集的第一个页面,这个页面作为我们的初始页面,方便我们通过该页面获取到其他链接,然后不断的采集下去,由于电商的特殊性,电商的商品数据都是有商品列表页的,所以我们可以将商品列表页作为采集的入口,如图所示:

    我们可以看到,如上图所示,这是京东-美妆个护-香水彩妆-口红 相关的商品数据,口红是三级类目,其中图中标1的是口红类目信息,2表明这个商品的分页数,一共有157页,其中红色 3部分表明 商品 主要区域中,一行是4个商品,但其实这一页有12行,也就说一页有4*12=48个商品,这是关于口红的所有商品,这个url=京东-口红类目商品列表页;大家可以访问来了解,这样,我们可以通过该页面来获取商品详情页链接和标题、价格等等,当然通过再访问详情页,可以了解更多商品详情数据,这里我们决定了这个页面是初始页,那我们如何利用selenium工具来实现模拟人的行为来登录这个页面呢,代码如下:

    System.setProperty("webdriver.chrome.driver", "D:\\SoftBuild\\chromedriver_win32\\chromedriver.exe");
            // driver即为浏览器对象
            WebDriver driver = new ChromeDriver();
            String url="https://search.jd.hk/Search?keyword=口红&enc=utf-8";
            driver.get(url);
            try {
                TimeUnit.SECONDS.sleep(10); // 10s的sleep,这样你就可以看到很多商品数据
            } catch (InterruptedException e) {
                System.out.println("Sleep方法出错");
            }
            driver.close(); //此方法是关闭窗口
            driver.quit(); // 此方法是关闭浏览器,整个浏览器进程也被关闭

    备注:其中chromedriver.exe的下载地址:chrome浏览器驱动下载链接,这里也会涉及到跟你自己电脑上谷歌浏览器的版本问题,大家可以看看这个网站的浏览器版本和驱动版本对应关系,网站:selenium(三)之webDriver与浏览器版本问题
    那我们再来下一个步骤。
    2、获取商品详情页链接
    首先要分析一下此页面的页面源码:

    
    <li class="gl-item">
    <div class="p-tab">
        <ul>
        ul>
    div>
    <div class="p-cnt">
        <div class="item hasComment" skuid="J_1994030801">
            <div class="p-img">
                <a href="//item.jd.hk/1994030801.html" target="_blank">
                <img src="//img11.360buyimg.com/cms/jfs/t2296/67/2540291745/1095/28285fbe/570e2074Nf22696dd.gif" data-original="//img10.360buyimg.com/n7/jfs/t18805/53/812555036/78482/c5235542/5aaa2226N3eac3269.jpg" class="lazy">a>
                <div class="other">
                    <div class="cj-concern">
                        <i>
                        i>
                        <em>关注em>
                    div>
                    <div class="p-operate">
                        <a href="javascript:;" skuid="1994030801" class="p-o-btn contrast J_contrast">
                        <i>
                        i>对比a>
                    div>
                div>
            div>
            <div class="price-icons">
                <div class="price">
                    <span>
                    <b>
                    b>
                    span>
                    <div class="sam">
                    div>
                div>
            div>
            <div class="p-name">
                <a href="//item.jd.hk/1994030801.html" target="_blank">
                <em>魅可(M.A.C) 【满199减100】 MAC魅可
                <font class="skcolor_ljg">口红font>显色丰润唇膏
                <font class="skcolor_ljg">口红font>3g Chili铁锈红/小辣椒色em>a>
            div>
            <div class="p-conduct">
                <em>em>
            div>
            <div class="p-buy">
                <div class="assess">
                    <a href="//item.jd.hk/1994030801.html#comments-list" target="_blank" class="comment">
                    <i>
                    i>
                    <em>9164em>a>
                div>
            div>
            <div class="p-icons" style="max-width: 200px">
            div>
        div>
    div>
    li>

    这是一个商品模块的代码,其中我们可以了解一下内容:

  • 标签< div class=”p-img”>是商品图片链接模块,这里面有商品链接和商品的图片链接。
  • 标签< div class=”p-name”>有商品标题、详情页链接等内容。
    其他也有相应的价格和销量的div标签,这里可以明显了解到这些内容。上一节我们知道如何访问这些内容,接下来我们可以来了解一下,怎么获取网页内容。
    代码:
  • System.setProperty("webdriver.chrome.driver", "D:\\SoftBuild\\chromedriver_win32\\chromedriver.exe");
            // driver即为浏览器对象
            WebDriver driver = new ChromeDriver();
            String url="https://search.jd.hk/Search?keyword=口红&enc=utf-8";
            driver.get(url);
            try {
                TimeUnit.SECONDS.sleep(10); // 10s的sleep,这样你就可以看到很多商品数据
            } catch (InterruptedException e) {
                System.out.println("Sleep方法出错");
            }
            WebElement divmain=driver.findElement(By.id("plist")); // 这个plist是页面所有商品所在div的id
            List divGoodlist=divmain.findElements(By.className("gl-item")); // 这个是
  • 的标签,通过className来获取所有匹配到的页面元素。正常这个大小应该是48。 for(WebElement goodEle:divGoodlist){ // 这里我们获取标题,通过这个来了解一下。 WebElement nameEle=goodEle.findElement(By.className("p-name")); WebElement aele=nameEle.findElement(By.tagName("a")); System.out.println("标题:"+aele.getText(); System.out.println("链接:"+aele.getAttribute("href")); } driver.close(); //此方法是关闭窗口 driver.quit(); // 此方法是关闭浏览器,整个浏览器进程也被关闭
  • 这样我们就获取到了商品详情页和标题。如果你要获取其他内容也都可以,但是要注意,你是通过class 属性来获取还是通过id 一以及其他 tag来获取,匹配该属性的元素是唯一的还是多个。不然容易报错。
    备注:
    京东的网页源码里class 属性比较少空格,天猫网页源码里面很多class都是空格,这里其实有区别,大家继续往下看天猫的数据获取。
    3、下一页
    这个很关键,因为这一页商品数据获取完了,就必须获取下一页的数据,这里我们看下网页中源码的下一页。

      

    其中a标签中有一个class=”pn-next”的,这个是点击下一页的操作,于是我们可以用来模拟鼠标点击。

    具体代码如下:

     /**
         * 京东的下一页操作
         * @param driver
         * @return
         */
        public boolean getNextPage(WebDriver driver){
            boolean falg=false;
            if(!driver.getPageSource().contains("下一页")){  // 判断页面中是否有下一页,因为有的入口只有一页数据,没有下一页的按钮
                return falg;
            }
            WebElement divElement= driver.findElement(By.className("pn-next")); // 获取这个元素
            divElement.click();  // 鼠标点击下一页
            System.out.println("----点击跳转到下一页----");
            return falg;
        }

    这段代码就成功跳转到下一页,这样就可以再获取下一页的商品数据。所以你需要自己组合这两个功能,先获取当前页面的商品数据,再判断有没有下一页,有下一页,就开始点击跳转到下一页,再获取下一页的商品数据。

    天猫数据获取

    1、采集首页

    这里天猫的数据是一行5个,一页是12行,那么基本一页就是60个商品,天猫只显示100页,如果你的关键词太少了,只显示前6000个商品,所以,你看到的100页并不代表只有100页,其实天猫商品的数据规模是远超京东的,所以碰到这个情况就必须细分采集入口,比如:从三级类目中再根据品牌来筛选,具体到三级类目下的某个品牌,这样条件多了,具体到品牌的商品数量就相对少了,举例就是:三级类目下有100个品牌,每个品牌有100页数据,那么就可以采集100*100*60=600000个商品了,这样可以爬取更多的商品链接。当然,你可以自己定义自己的采集策略。

    2、获取商品属性
    查看页面源码:

    <div class="product " data-id="544794131401" data-atp="a!,,50010808,,,,,,,,">
        <div class="product-iWrap">
            <div class="productImg-wrap">
                <a href="//detail.tmall.hk/item.htm?id=544794131401&skuId=3414795933847&areaId=330108&standard=1&user_id=1954290542&cat_id=55950003&is_b=1&rn=a48427a02adeec0fd36ebb3a42aef0d8" class="productImg" target="_blank" data-p="1-10">
                <img src="" "//img.alicdn.com/bao/uploaded/i5/tb1inzzpxxxxxbsapxxcwky_xxx_053854.jpg_b.jpg"/>
                a>
            div>
            <p class="productPrice">
                <em title="255.00"><b>¥b>255.00em>
                <i class="national-flag tm-unit-FR">i>
            p>
            <div class="productTitle productTitle-spu">
                
                <a href="//detail.tmall.hk/item.htm?id=544794131401&skuId=3414795933847&areaId=330108&standard=1&user_id=1954290542&cat_id=55950003&is_b=1&rn=a48427a02adeec0fd36ebb3a42aef0d8" target="_blank" title="滋润 保湿 防水" data-p="1-11">Dior/迪奥 烈艳蓝金唇膏a>
                <a class="lightspot" href="//detail.tmall.hk/item.htm?id=544794131401&skuId=3414795933847&areaId=330108&standard=1&user_id=1954290542&cat_id=55950003&is_b=1&rn=a48427a02adeec0fd36ebb3a42aef0d8" target="_blank" title="滋润 保湿 防水" data-p="1-11">滋润 保湿 防水a>
            div>
            <div class="productShop" data-atp="b!1-3,{user_id},,,,,,">
                <a class="productShop-name" href="//store.taobao.com/search.htm?user_number_id=1954290542&rn=a48427a02adeec0fd36ebb3a42aef0d8" target="_blank">
    骏然海外专营店
                a>
            div>
            <p class="productStatus">
                <span>该款月成交 <em>4.2万笔em>span>
                <span data-icon="small" class="ww-light ww-small m_wangwang J_WangWang" data-item="544794131401" data-nick="骏然海外专营店" data-tnick="骏然海外专营店" data-display="inline" data-atp="a!1-2,,,,,,,1954290542">span>
            p>
        div>
    div>

    这是天猫的商品模块html代码,基本我也就不讲了,重点还是你自己通过元素定位,定位到相应的标签上,标签上有id那就根据id定位,没有id,那就根据class来定位。

    代码:

    System.setProperty("webdriver.chrome.driver", "D:\\SoftBuild\\chromedriver_win32\\chromedriver.exe");
            // driver即为浏览器对象
            WebDriver driver = new ChromeDriver();
            String tmdUrl="https://list.tmall.hk/search_product.htm?spm=a2231.7718719.2014120102.33.4a5c12feFloXgU&cat=55950003&sort=s&acm=lb-zebra-34359-425776.1003.8.519261&_ksTS=1429862287170_954&from=sn_1_rightnav&_input_charset=utf-8&style=g&s=0&search_condition=7&industryCatId=52830004&callback=__jsonp_cb&active=1&abtest=null&scm=1003.8.lb-zebra-34359-425776.ITEM_14455541646861_519261";
    
            driver.get(tmdUrl);
            WebElement goodmain=driver.findElement(By.id("J_ItemList")); // 商品模块的div区域
            List<WebElement> goodelement=driver.findElements(By.className("product-iWrap"));
            String falg="productTitle productTitle-spu";
            for(WebElement goodele :goodelement){
                WebElement div= goodele .findElement(By.cssSelector(falg));
                List<WebElement> acl=div.findElements(By.tagName("a"));  // 将特定div下的所有a标签都获取到了。
                // 后续自己处理
            }

    2、下一页
    天猫的下一页数据也很容易获取,可以自己去参考京东的那个自己做一个,尝试测试一下;

    爬虫过程中碰到的问题

    在爬取商品数据的过程中碰到了很多问题,这些问题也是其他爬虫工作者碰到的问题,这里写出来,其实我觉得所有的爬虫的重点就是解决这些问题,其他都是小问题,这些问题解决了,爬虫就很顺利。

    1、验证码

    验证码就是为了为了反爬,不让你爬取,但是如今,验证码的问题也基本都没有太多问题,许多打码平台可以帮助我们解决这个问题,当然自己去用机器学习或者深度学习来训练模型,然后来实现一个识别验证码。

    2、登录

    天猫和淘宝数据都会出现这个问题,当你频繁的访问网站的时候,会跳转到登录界面,要求用户登录,这个问题的解决是用大量的手机来申请淘宝账号,然后利用这些账号获取cookie ,然后携带cookie去访问这些页面,也可以当出现验证码的时候实现一个账号登录的功能。

    3、限制访问次数,加载不了页面内容

    这个问题也会出现,但是如果有账号的话,这个问题相对不会那么激进,不会那么容易被触发,所以这里利用动态IP技术来说相对可以解决,不过不推荐使用免费的ip,免费的ip容易获取,但是也容易被反爬冲的网站拿来更好的限制这些ip的访问,所以花钱购买有用的ip吧,这个没得办法,这些IP最好也是全国各地的IP,这样就不会被反爬。

    4、携带cookie

    电商平台利用cookie做了很多事情,他们利用cookie来表明用户身份,和服务器的session一起工作,其中我了解到的比较少,但感觉cookie可以有效的针对直接的http请求,其实selenium工具是不需要自己在代码里设置cookie的,因为selenium工具是启动一个浏览器,浏览器访问网站是自己生成一些cookie的,这个可以自己尝试一下,查看selenium工具启动的浏览器的后台cookie。

    selenium 总结

    这个工具是在有界面的情况下,比如Windows和带界面的Linux环境下,如果要部署到生产环境中就会有一个问题,一般的生产环境都是Linux无界面版本,所以采取的方案就是:
    1、部署沙盒,xvfb软件就是一个部署在服务器的沙盒软件,这样,selenium工具启动一个浏览器可以直接运行在xvfb中。
    2、使用phantomjs工具,此工具也是一个浏览器工具,可以当做浏览器使用,有了这个工具就可以不使用谷歌浏览器等等。

    总结

    京东数据的反爬机制相对薄弱,可能京东还没开始注重这一块,淘宝和天猫相对较为成熟,这里的反爬都是针对这两者的,希望这些问题可以帮助大家,特别是有兴趣的同学,可以手动的去了解一下。

    参考博客

    学习教程
    selenium java 浏览器操作

    你可能感兴趣的:(爬虫)