全國到底有多少人在看直播?我用Node寫了個爬蟲統計了一下

火爆的直播

近幾年直播能夠說是至關火爆,可是直播間裏動輒成百上千萬的人氣讓人禁不住產生疑惑,怎麼會有這麼高的人氣?難道全國人民都在看直播?javascript

爲了解決這個困擾我已久的問題,我專門去學習了node爬蟲的相關知識,下面就跟你們分享一下。php

鬥魚

先從日常看的最多的鬥魚開始,後來也證實鬥魚是最簡單的一個。css

經過去分析鬥魚的網站發現,鬥魚有一個所有分類的頁面https://www.douyu.com/directory html

這個頁面已經統計好了全部分類下的總人氣,接下來要作的就是經過DOM解析操做拿到每一個分類下的總人數,而後把這些人數相加就能夠。

在這裏用到了cheerio這個包,這個包就至關於服務端的jQuery,用在服務器端須要對DOM進行操做的地方,使用方法也跟jQuery差很少。java

由於鬥魚的網頁通過了gzip壓縮,還要用到zlib,這個包的做用是解壓縮。node

// 引入https模塊
const https = require('https')
// zlib包,用於解壓縮
const zlib = require('zlib')
// cheerio包,提供了相似jQuery的功能
const cheerio = require("cheerio");

function douyu () {
    // 建立請求對象
    let req = https.request('https://www.douyu.com/directory', res => {
        // 接收數據
        let chunks = []
        // 監聽到數據就存儲起來
        res.on('data', chunk => {
            chunks.push(chunk)
        })
        // 數據傳輸結束
        res.on('end', () => {
            // 拼接數據
            var buffer = Buffer.concat(chunks)
            // 使用zlib解壓縮
            zlib.gunzip(buffer, function (err, decoded) {
                // gzip解壓後的html文本
                let html = decoded.toString()
                // 使用cheerio解析html
                let $ = cheerio.load(html)
                // 獲取包含直播數據的元素列表
                let list = $('#allCate .layout-Module-container .layout-Classify-list .layout-Classify-item .layout-Classify-card')
                // 解析dom,取出標籤中的數據
                const dataList = {}
                Array.prototype.map.call(list, item => {
                    let key = '', value = ''
                    item.children.forEach(childrenItem => {
                        if (childrenItem.name === 'strong') {
                            key = childrenItem.children[0] ? childrenItem.children[0].data : '空'
                        } else if (childrenItem.name === 'div') {
                            value = $(childrenItem).find('span').html()
                            value = unescape(value.replace(/&#x/g, '%u').replace(/;/g, ''))
                        }
                    })
                    dataList[key] = value
                })
                // 相加得出總人數
                let total = 0
                for (let key in dataList) {
                    let value = dataList[key]
                    // 處理單位爲萬的數字
                    if (value.indexOf('萬') != -1) value = Number.parseFloat(value) * 10000
                    total += Number.parseFloat(value) ? Number.parseFloat(value) : 0
                }
                console.log(`鬥魚:${total}`)
            })
        })
    })
    // 發送請求
    req.end()
}
複製代碼

虎牙

查看虎牙的網站發現並無像鬥魚同樣提供統計的分類列表,可是找到了該網站查詢直播間列表信息的接口https://www.huya.com/cache.php?m=LiveList&do=getLiveListByPage&tagAll=0&page=1。經過該接口能夠拿到全部直播間的信息,其中就包含了每一個直播間的人數,接下來就是把每一個直播間的人數相加就能夠獲得該平臺的總人數。web

// 引入https模塊
const https = require('https')

function huya {
    // 初始化總數
    let total = 0
    // 初始化總頁數
    let totalPage = 1
    // 初始化當前頁數
    let currentPage = 1
    // 與鬥魚同樣的開始獲取、處理數據
    huyaGetData(currentPage)
    function huyaGetData(currentPage) {
        let req = https.request(`https://www.huya.com/cache.php?m=LiveList&do=getLiveListByPage&tagAll=0&page=${currentPage}`, res => {
            const chunks = []
            res.on('data', chunk => {
                chunks.push(chunk)
            })
            res.on('end', () => {
                const data = JSON.parse(Buffer.concat(chunks).toString('utf-8')).data
                const dataList = data.datas
                // 拿到總頁數
                totalPage = data.totalPage
                // 累加直播間的人數
                total = dataList.reduce((total, item) => {
                    return total + Number.parseInt(item.totalCount)
                }, total)
                // 獲取下一頁的數據
                currentPage += 1
                if (currentPage < totalPage) {
                    huyaGetData(currentPage)
                } else {
                    console.log(`虎牙:${total}`)
                }
            })
        })
        req.end()
    }
}
複製代碼

嗶哩嗶哩

嗶哩嗶哩頁面中也有與虎牙類似的所有直播間查詢接口,統計方法與虎牙差很少,這裏就再也不贅述了。chrome

YY

在YY的網頁中並無提供所有直播間的查詢接口,只提供了單一分類的查詢接口https://www.yy.com/more/page.action?biz=sing&subBiz=idx&page=3&moduleId=308&pageSize=60,而每一個分類查詢要傳過去的參數值都不同,又沒有任何規律可循,因此如今要拿到每一個分類查詢所須要的信息,以後的查詢就跟虎牙同樣了。api

那如今要作的就是拿到接口所需信息,經過分析頁面發現每一個分類直播的列表頁都有一個pageInfo的全局變量,這裏邊就包含了查詢所需的全部信息。咱們能夠拿到這些分類頁面的html文件,而後解析出其中的pageInfo變量。可是這裏爲了演示,咱們使用另外一個方法Selenium來解決這個問題。瀏覽器

Selenium是一個Web應用的自動化測試框架,用在爬蟲中可使用它打開瀏覽器,用代碼去模擬人的真實操做去爬取須要的信息,突破反爬蟲手段的限制。

要使用Selenium,首先要根據平臺去下載對應的webdriver這裏chromeDriver的下載地址,根據本身電腦上Chrome的版本下載對應的chromeDriver,下載好以後複製到項目根目錄。別的瀏覽器能夠自行去找對應的包下載。

而後在項目中安裝selenium-webdriver包的依賴。

const { Builder, By } = require('selenium-webdriver')

async function getYYPageInfoList() {
    // 構建WebDriver對象
    let driver = await new Builder().forBrowser('chrome').build();
    // 打開網頁
    await driver.get('https://www.yy.com/catalog');
    // 獲取分類標籤列表
    let aList = await driver.findElements(By.css('.w-video-module-cataloglist a'))
    // 獲取分類頁面地址列表
    let hrefList = []
    for (let i = 0; i < aList.length - 1; i++) {
        let href = await aList[i].getAttribute('href')
        hrefList.push(href)
    }
    // 打開分類頁面
    for (let i = 0; i < hrefList.length - 1; i++) {
        await driver.get(hrefList[i])
        // 在頁面中執行 return pageInfo, 取到pageInfo
        driver.executeScript('return pageInfo').then(function (obj) {
            // 存儲pageInfo信息
            pageInfoList.push(obj)
        })
    }
    // 退出瀏覽器
    driver.quiet()
    return pageInfoList
}
複製代碼

統計結果

統計結果的地址:http://liupenglong.com/live/index.html(每五分鐘統計一次)

能夠看到目前僅僅統計出了鬥魚、虎牙、嗶哩嗶哩、YY的數據,總人數已經超過全國總人口了,算上別的沒有統計上的。。。結果可想而知,估計全球人民都在看中國的直播了。

接下來有時間會把別的平臺的也統計出來,最終但願能推算出來真正在看直播的人數,你們若是有什麼好的想法能夠評論交流一下。

相關文章
相關標籤/搜索