“智慧选品”项目主要是方便采购人员了解其他竞品平台的商品数据,将其他平台上卖的特别好的商品数据展示给采购人员,方便他们去采购商品,扩大公司自己的商品,所以就需要爬取其他平台的数据,本着需求出发,这里主要爬取天猫国际、京东全球购、淘宝全球购的商品属性数据,包括标题、品牌、价格、销量、评论数、收藏数、好评数等等,再利用推荐算法对数据排序。
备注说明:
1、首先商品数据获取,其实京东全球购的数据获取不到销量,而且评论数也不是准确数字,这里只尽可能的采集数据,实在没有的商品属性也没办法。
2、新品识别其实是一个重点,因为你需要把其他平台中不存在我们商品数据的商品找出来,而且要精细到规格,这里就比较难受,因为像口红这样的商品,可能颜色就有10多个,要找出不存在我们商品数据中但在其他平台上的商品,难度较大,这里有很多问题,目前讨论出来的方法是,利用商品标题和商品一些属性做相似度匹配,这准确率实际效果不高。
3、推荐算法这里比较简单,后面单独开一篇博客讲解。
这里使用的技术都是一样的,我先讲解利用什么技术手段来获取数据,其实目前获取数据手段也较多:
方法已将讲解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>
这是一个商品模块的代码,其中我们可以了解一下内容:
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、下一页
这个很关键,因为这一页商品数据获取完了,就必须获取下一页的数据,这里我们看下网页中源码的下一页。
"J_bottomPage" class="p-wrap">
"p-num">
"/search?keyword=%E5%8F%A3%E7%BA%A2&enc=utf-8" class="curr">1</a>
%E5%8F%A3%E7%BA%A2&enc=utf-8&page=2" class="">2
%E5%8F%A3%E7%BA%A2&enc=utf-8&page=3" class="">3
" class="pn-break">... %E5%8F%A3%E7%BA%A2&enc=utf-8&page=157" class="">157
%E5%8F%A3%E7%BA%A2&enc=utf-8&page=2" class="pn-next">下一页>
"> 共157页 到第
其中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、下一页
天猫的下一页数据也很容易获取,可以自己去参考京东的那个自己做一个,尝试测试一下;
在爬取商品数据的过程中碰到了很多问题,这些问题也是其他爬虫工作者碰到的问题,这里写出来,其实我觉得所有的爬虫的重点就是解决这些问题,其他都是小问题,这些问题解决了,爬虫就很顺利。
验证码就是为了为了反爬,不让你爬取,但是如今,验证码的问题也基本都没有太多问题,许多打码平台可以帮助我们解决这个问题,当然自己去用机器学习或者深度学习来训练模型,然后来实现一个识别验证码。
天猫和淘宝数据都会出现这个问题,当你频繁的访问网站的时候,会跳转到登录界面,要求用户登录,这个问题的解决是用大量的手机来申请淘宝账号,然后利用这些账号获取cookie ,然后携带cookie去访问这些页面,也可以当出现验证码的时候实现一个账号登录的功能。
这个问题也会出现,但是如果有账号的话,这个问题相对不会那么激进,不会那么容易被触发,所以这里利用动态IP技术来说相对可以解决,不过不推荐使用免费的ip,免费的ip容易获取,但是也容易被反爬冲的网站拿来更好的限制这些ip的访问,所以花钱购买有用的ip吧,这个没得办法,这些IP最好也是全国各地的IP,这样就不会被反爬。
电商平台利用cookie做了很多事情,他们利用cookie来表明用户身份,和服务器的session一起工作,其中我了解到的比较少,但感觉cookie可以有效的针对直接的http请求,其实selenium工具是不需要自己在代码里设置cookie的,因为selenium工具是启动一个浏览器,浏览器访问网站是自己生成一些cookie的,这个可以自己尝试一下,查看selenium工具启动的浏览器的后台cookie。
这个工具是在有界面的情况下,比如Windows和带界面的Linux环境下,如果要部署到生产环境中就会有一个问题,一般的生产环境都是Linux无界面版本,所以采取的方案就是:
1、部署沙盒,xvfb软件就是一个部署在服务器的沙盒软件,这样,selenium工具启动一个浏览器可以直接运行在xvfb中。
2、使用phantomjs工具,此工具也是一个浏览器工具,可以当做浏览器使用,有了这个工具就可以不使用谷歌浏览器等等。
京东数据的反爬机制相对薄弱,可能京东还没开始注重这一块,淘宝和天猫相对较为成熟,这里的反爬都是针对这两者的,希望这些问题可以帮助大家,特别是有兴趣的同学,可以手动的去了解一下。
学习教程
selenium java 浏览器操作