上天的Node.js之爬蟲篇 15行程式碼爬取京東資源

Jeery_譚金傑發表於2019-03-22

難道爬蟲只能用 python 做? 不,我們上天的 Node.js 也可以做!

  • 需要準備的包
    • Node.js的最新版本 下載地址 Node.js官網
    • npm 包管理器下載 下載最新的官網版本 Node.js會自帶npm
    • npm的第三方包 puppeteer 在對應的js檔案內執行命令列工具npm i puppeteer -D即可

爬蟲在獲取某些有保護機制的網頁時可能會失效

初入江湖 -自在地境篇

const puppeteer = require('puppeteer'); //  引入依賴  
(async () => {   //使用async函式完美非同步 
    const browser = await puppeteer.launch();  //開啟新的瀏覽器
    const page = await browser.newPage();   // 開啟新的網頁 
    await page.goto('https://www.jd.com/');  //前往裡面 'url' 的網頁
    const result = await page.evaluate(() => {   //這個result陣列包含所有的圖片src地址
        let arr = []; //這個箭頭函式內部寫處理的邏輯  
        const imgs = document.querySelectorAll('img');
        imgs.forEach(function (item) {
            arr.push(item.src)
        })
        return arr 
    });
    await browser.close()
})()

  複製過去 使用命令列命令 ` node 檔名 ` 就可以執行獲取爬蟲資料了 

複製程式碼

這個puppeteer的包 ,其實是替我們開啟了另一個瀏覽器,重新去開啟網頁,獲取它們的資料。

瀟灑入世 -逍遙天境篇

  • 上面只爬取了京東首頁的圖片內容,假設我的需求進一步擴大,需要爬取京東首頁 中的所有<a> 標籤對應的跳轉網頁中的所有 title的文字內容,最後放到一個陣列中

  • 我們的async函式上面一共分了五步, 只有 puppeteer.launch() , browser.newPage(), browser.close() 是固定的寫法。

  • page.goto 指定我們去哪個網頁爬取資料,可以更換內部url地址,也可以多次 呼叫這個方法。

  • page.evaluate 這個函式,內部是處理我們進入想要爬取網頁的資料邏輯

  • page.gotopage.evaluate兩個方法,可以在async內部呼叫多次, 那意味著我們可以先進入京東網頁,處理邏輯後,再次呼叫page.goto這個函式,

注意,上面這一切邏輯,都是puppeteer這個包幫我們在看不見的地方開啟了另外一個 瀏覽器,然後處理邏輯,所以最終要呼叫browser.close()方法關閉那個瀏覽器。

  • 這時候我們對上一篇的程式碼進行優化,爬取對應的資源。
 const puppeteer = require('puppeteer');
(async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('https://www.jd.com/');
    const hrefArr = await page.evaluate(() => {
        let arr = [];
        const aNodes = document.querySelectorAll('.cate_menu_lk');
        aNodes.forEach(function (item) {
            arr.push(item.href)
        })
        return arr
    });
    let arr = [];
    for (let i = 0; i < hrefArr.length; i++) {
        const url = hrefArr[i];
        console.log(url) //這裡可以列印 
        await page.goto(url);
        const result = await page.evaluate(() => { //這個方法內部console.log無效 
            
              return  $('title').text();  //返回每個介面的title文字內容
        });
        arr.push(result)  //每次迴圈給陣列中新增對應的值
    }
    console.log(arr)  //得到對應的資料  可以通過Node.js的 fs 模組儲存到本地
    await browser.close()
})()

複製程式碼

上面有天坑 page.evaluate函式內部的console.log不能列印,而且內部不能獲取外部的變數,只能return返回, 使用的選擇器必須先去對應介面的控制檯實驗過能不能選擇DOM再使用,比如京東無法使用querySelector。這裡由於 京東的分介面都使用了jQuery,所以我們可以用jQuery,總之他們開發能用的選擇器,我們都可以用,否則就不可以。

威震武林 -神遊玄境篇

資料在這個時代非常珍貴,上面兩個能獲取一些指定的特定資源,按照網頁的設計邏輯,選定特定的href的地址, 可以先直接獲取對應的資源,也可以通過再次使用 page.goto方法進入,再呼叫page.evaluate() 處理邏輯。 這裡就不做過多介紹了,畢竟Node.js是可以上天的,或許未來它真的什麼都能做。這麼優質簡短的教程,請收藏 或者轉發給您的朋友,謝謝。

相關文章