nodejs + puppeteer 模擬淘寶登錄並采集數據


熟悉puppeteer模塊時做的小demo,代碼十分簡單易懂,分享給大家交流學習,請勿惡意抓取或做違反國家政策的行為。

 

一、前期准備工作

        首先需要安裝nodejs,並初始化一個項目,安裝puppeteer模板以及log4js日志模板並保存。

   npm install puppeteer --save-dev

   npm install log4js --save-dev

 

二、先引用模塊並定義相關變量以及日志配置

 1 var puppeteer = require('puppeteer');
 2 var log4js = require('log4js');
 3 var logger = log4js.getLogger();
 4 // 結果集合
 5 var resultList = [];
 6 // 采集最大頁碼
 7 var maxPage = 10;
 8 // 當前采集頁碼
 9 var nowPage = 1;
10 
11 
12 log4js.configure({
13     appenders: {
14         xcLogFile: {
15             type: "dateFile",
16             filename: __dirname + '/logs/log4js.log',//您要寫入日志文件的路徑
17             //compress: true,//(默認為false) - 在滾動期間壓縮備份文件(備份文件將具有.gz擴展名)
18             pattern: "-yyyy-MM-dd-hh",//(可選,默認為.yyyy-MM-dd) - 用於確定何時滾動日志的模式。格式:.yyyy-MM-dd-hh:mm:ss.log
19             encoding: 'utf-8',//default "utf-8",文件的編碼
20             maxLogSize: 2048000 //文件最大存儲空間,當文件內容超過文件存儲空間會自動生成一個文件xxx.log.1的序列自增長的文件
21         },
22         xcLogConsole: {
23             type: 'console'
24         }
25     },
26     categories: {
27         default: {
28             appenders: ['xcLogFile'],
29             level: 'all'
30         },
31         xcLogFile: {
32             appenders: ['xcLogFile'],
33             level: 'all'
34         },
35         xcLogConsole: {
36             appenders: ['xcLogConsole'],
37             level: log4js.levels.ALL
38         }
39     }
40 })
41 logger.level = 'debug';

 

 三、實現淘寶模擬登錄

  
   需要特別說明的是其中有一步跳過 selenium檢測機制的代碼,是十分重要的,如果沒加將會無限循環驗證碼。

await page.evaluate(async () => {
  Object.defineProperty(navigator, 'webdriver', { get: () => false }) })

const action = (async () => {
    // 定義瀏覽器無頭模式、分辨率以及關閉沙盒模式等等。
    const browser = await puppeteer.launch({
        headless: false,
        defaultViewport: {
            width: 1300,
            height: 900
        },
        args: ['--no-sandbox', '--disable-setuid-sandbox']
    });
    // 新建頁面
    var page = await browser.newPage();
    
    // 設定瀏覽器UserAgent
    await page.setUserAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36');
    // 跳轉淘寶登錄頁
    await page.goto('https://login.taobao.com/member/login.jhtml?redirectURL=https%3A%2F%2Fwww.taobao.com%2F');
    // 這一步十分重要,因為大部分大型網站都會對selenium機制進行檢測,例如navigator.webdriver,navigator.languages等等。
    // 這一步就是把navigator的一些屬性方法等等注入到瀏覽器中,繞過這些檢測機制。
    await page.evaluate(async () => {
        Object.defineProperty(navigator, 'webdriver', { get: () => false })
    })
    // 等待登錄按鈕加載完畢
    await page.$('.password-login');
    // 自動輸入賬號,間隔頻率隨機數300毫秒內
    await page.type('input[id=fm-login-id]', '你的賬號', { delay: (parseInt(Math.random() * 300)) });
    // 自動輸入密碼,間隔頻率隨機數300毫秒內
    await page.type('input[id=fm-login-password]', '你的密碼)', { delay: (parseInt(Math.random() * 300)) })
    // 點擊登錄按鈕
    await page.click('.password-login');

    console.log('登錄成功!')

    // 獲取cookies
    // cookies = await page.evaluate(() => document.cookie);
    // console.log(cookies);

    // 等待頁面加載完畢
    await page.waitForNavigation()

    // 搜索關鍵字
    var keyName = '連衣裙';
    // 等待輸入框加載完畢
    await page.$('#q');
    // 輸入關鍵字
    await page.type('input[id=q]', keyName, { delay: 300 });
    // 點擊搜索按鈕
    await page.click('.btn-search');

    // 等待5秒后進入采集方法
    await page.waitFor(5000);

    console.log('采集開始...');
    gather(page);
})();

 

 四、實現淘寶數據采集

const gather = async (page) => {
    await page.waitFor(5000);

    // 等待下一頁的按鈕
    var nextBtn = await page.waitForSelector('#mainsrp-pager .next:not(.next-disabled)');

    // 數據對象
    console.log(`進行第${nowPage}頁數據采集...`)
    // 執行JS方法,將獲取到的結果返回
    var content = await page.evaluate(() => {
        // 這里的:not(.item-ad)是指不需要推廣的商品,如果需要則直接去掉即可。
        var itemList = document.querySelectorAll('#mainsrp-itemlist .J_MouserOnverReq:not(.item-ad)');
        var dataList = [];
        for (var i = 0; i < itemList.length; i++) {
            var data = {};
            var item = itemList[i];
            // 商品名稱
            data.name = item.querySelector('.title .J_ClickStat').innerText;
            // 價格
            data.price = item.querySelector('.price strong').innerText;
            // 地區
            data.area = item.querySelector('.location').innerText;
            // 店鋪名稱
            data.shopName = item.querySelector('.shopname').innerText;
            // 月銷量
            data.sellerMonth = item.querySelector('.deal-cnt').innerText || 0;
            if (data.sellerMonth) {
                data.sellerMonth = data.sellerMonth.replace('人付款', '');
            }
            dataList.push(data);
        }
        return dataList;
    });
    console.log(`采集到${content.length}條數據!`);
    content.map(item => {
        // 這里本應是數據庫操作,但是篇幅有限就直接寫在日志里。
        logger.debug(JSON.stringify(item));
        resultList.push(item);
    })
    // 判斷頁碼是否小於定義的采集最大頁碼,並且存在下一頁按鈕。
    if (nowPage < maxPage && nextBtn) {
        nowPage++;
        page.click('#mainsrp-pager .next');
        gather(page);
    }
    else {
        console.log(`采集完畢,一共采集${maxPage}頁,${resultList.length}條數據!`);
    }
}

 

代碼都是實測沒問題的,這里的maxPage也本應是動態獲取的,但都比較簡單,有問題的小伙伴可以留言問我,轉載請注明出處,謝謝!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM