1. 程式人生 > >爬取天貓國際、京東全球購、淘寶全球購的商品資料

爬取天貓國際、京東全球購、淘寶全球購的商品資料

公司內部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.selenium</groupId>
            <artifactId>selenium-server</artifactId>
            <version>2.53.0</version>
     </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>9164</em></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<WebElement> divGoodlist=divmain.findElements(By.className("gl-item")); // 這個是<li class="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、下一頁
    這個很關鍵,因為這一頁商品資料獲取完了,就必須獲取下一頁的資料,這裡我們看下網頁中原始碼的下一頁。

      <div id="J_bottomPage" class="p-wrap"> 
       <span class="p-num"> 
        <a href="/search?keyword=%E5%8F%A3%E7%BA%A2&amp;enc=utf-8" class="curr">1</a> 
        <a href="/search?keyword=%E5%8F%A3%E7%BA%A2&amp;enc=utf-8&amp;page=2" class="">2</a> 
        <a href="/search?keyword=%E5%8F%A3%E7%BA%A2&amp;enc=utf-8&amp;page=3" class="">3</a> 
        <a href="javascript:;" class="pn-break">...</a> <a href="/search?keyword=%E5%8F%A3%E7%BA%A2&amp;enc=utf-8&amp;page=157" class="">157</a> 
        <a href="/search?keyword=%E5%8F%A3%E7%BA%A2&amp;enc=utf-8&amp;page=2" class="pn-next">下一頁<i>&gt;</i></a> 
      </span> 
      <span class="p-skip"> <em>共<b>157</b>頁&nbsp;&nbsp;到第</em> 
    </span> 
      </div>

    其中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&amp;skuId=3414795933847&amp;areaId=330108&amp;standard=1&amp;user_id=1954290542&amp;cat_id=55950003&amp;is_b=1&amp;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>&yen;</b>255.00</em>
                <i class="national-flag tm-unit-FR"></i>
            </p>
            <div class="productTitle productTitle-spu">
                <!--product.spuTitleShow:true ,product.itemTitleShow:$product.itemTitleShow-->
                <a href="//detail.tmall.hk/item.htm?id=544794131401&amp;skuId=3414795933847&amp;areaId=330108&amp;standard=1&amp;user_id=1954290542&amp;cat_id=55950003&amp;is_b=1&amp;rn=a48427a02adeec0fd36ebb3a42aef0d8" target="_blank" title="滋潤 保溼 防水" data-p="1-11">Dior/迪奧 烈豔藍金脣膏</a>
                <a class="lightspot" href="//detail.tmall.hk/item.htm?id=544794131401&amp;skuId=3414795933847&amp;areaId=330108&amp;standard=1&amp;user_id=1954290542&amp;cat_id=55950003&amp;is_b=1&amp;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&amp;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工具,此工具也是一個瀏覽器工具,可以當做瀏覽器使用,有了這個工具就可以不使用谷歌瀏覽器等等。

    總結

    京東資料的反爬機制相對薄弱,可能京東還沒開始注重這一塊,淘寶和天貓相對較為成熟,這裡的反爬都是針對這兩者的,希望這些問題可以幫助大家,特別是有興趣的同學,可以手動的去了解一下。

    參考部落格