用node+puppeteer騰訊視訊爬取例項

push-over發表於2019-03-13

專案簡介

通過騰訊電影的url地址和爬取的頁數來進行頁面資料的爬取。

專案地址

github地址

使用庫

  • puppeteer - 抓取資料
  • chalk - 更改console.log
  • file-box - 打包圖片用於wechaty傳送
  • fs - 寫入檔案

基本思路

  • 抓取騰訊視訊電影的資料
  • 格式化列印的資訊
  • 開啟要爬取的連結
  • 睡眠幾秒之後再爬取下一頁

安裝模組

# 安裝puppeteer
npm install puppeteer --save
# puppeteer 需要安裝 chromium,可以選擇修改 puppeteer 的下載源:
npm config set puppeteer_download_host https://npm.taobao.org/mirrors

# 安裝chalk
npm install chalk --save
複製程式碼

最終程式碼

const puppeteer = require('puppeteer');
const chalk = require('chalk');
const fs = require('fs');

// 延遲執行
const sleep = time => new Promise(resolve => {
    setTimeout(resolve, time);
});

// console.log 簡寫
const log = console.log;
// 要爬取的網頁數量
const TOTAL_PAGE = 150;

// 爬取的連結
// const url = `https://v.qq.com/x/list/movie?itype=-1&offset=0`;
const url = `https://v.qq.com/channel/movie?listpage=1&channel=movie&itype=100062`;

// 格式化進度輸出
function formatProgress(current) {
    let percent = (current / TOTAL_PAGE) * 100;
    let done = ~~(current / TOTAL_PAGE * 40);
    let left = 40 - done;
    let str = `當前進度:[${''.padStart(done, '=')}${''.padStart(left, '-')}]  ${percent}%`;
    return str;
}

(async () => {
    // 啟動瀏覽器環境
    const browser = await puppeteer.launch({
        // headless: false,
        // slowMo: 250
    });
    log(chalk.green('服務正常啟動'))

    try {
        const page = await browser.newPage(); // 開啟一個新的頁面
        // 監聽內部的console訊息
        page.on('console', message => {
            if (typeof message == 'object') {
                console.dir(message);
            } else {
                log(chalk.blue(message))
            }
        });

        // 開啟要爬取的連結
        await page.goto(url, {
            waitUntil: 'networkidle2' // 網路空閒說明已載入完畢
        });

        log(chalk.yellow('頁面初次載入完畢'));
	await sleep(3000);
        for (let i = 1; i <= TOTAL_PAGE; i++) {
            const submit = await page.$('.page_next'); // 獲取下一頁按鈕
            if (!submit) {
                chalk.red('資料獲取完畢');
                return;
            }
            await submit.click(); // 模擬點選跳轉下一頁
	    await sleep(3000);
            await page.waitFor(2500); // 等待頁面載入完畢
            console.clear();
            // 列印當前的爬取進度
            log(chalk.yellow(formatProgress(i)));
            log(chalk.yellow('頁面資料載入完畢'));

            await handleData(); // 執行方法
            await sleep(3000);
            await page.waitFor(2500); // 一個頁面爬取完畢以後稍微歇歇
        }

        await browser.close();
        log(chalk.green('服務正常結束'));

        // 獲取瀏覽器內部內容
        async function handleData() {
            const result = await page.evaluate(() => {
                var $ = window.$; // // 拿到頁面上的JQuery
                var itemList = $('.list_item'); // 拿到所有的item
                var links = []; // 儲存爬取的資料
                // 迴圈寫進陣列
                itemList.each((index, item) => {
                    let i = $(item);
                    let vid = i.find('.figure').data('float'); // id
                    let link = i.find('.figure').attr('href'); // 連結地址
                    let star = i.find('.figure_desc').attr('title'); // 主演
                    let title = i.find('.figure_pic').attr('alt'); // 電影名稱
                    let poster = i.find('.figure_pic').attr('src'); // 封面圖片
                    let count = i.find('.figure_count').text(); // 播放量
                    // 存進之前定義好的陣列中
                    links.push({
                        vid,
                        title,
                        count,
                        star,
                        poster,
                        link
                    });
                });
                return links; // 返回資料
            });

            // 寫入json檔案中
            fs.writeFile('./movie.json', JSON.stringify(result, null, '\t', {
                'flag': 'a'
            }), function (err) {
                if (err) {
                    throw err;
                }
            });
            log(chalk.yellow('寫入資料完畢'));
        }
    } catch (error) {
        console.log(error)
        log(chalk.red('服務意外終止'))
        await browser.close()
    } finally {
        process.exit(0);
    }
})();
複製程式碼

第一次寫,寫的不好請大家見諒,後續會繼續努力的。

相關文章