Greasy Fork

Greasy Fork is available in English.

抖音直播间人数显示

显示抖音直播间实时观看人数

当前为 2024-12-19 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         抖音直播间人数显示
// @namespace    https://www.phpnbw.com/
// @version      1.8.2
// @description  显示抖音直播间实时观看人数
// @author       phpnbw
// @match        https://live.douyin.com/*
// @match        https://www.douyin.com/*
// @exclude      https://www.douyin.com/channel*
// @grant        GM_xmlhttpRequest
// @license      Copyright phpnbw
// @connect      dyapi.phpnbw.com
// ==/UserScript==

(function() {
    'use strict';

    // 缓存 webcastId
    let cachedWebcastId = null;
    let cachedUrl = null;

    function getWebcastId() {
        const currentUrl = window.location.href;

        // 如果URL没有变化且已有缓存的webcastId,直接返回缓存值
        if (currentUrl === cachedUrl && cachedWebcastId !== null) {
            // console.log('使用缓存的直播间ID:', cachedWebcastId);
            return cachedWebcastId;
        }

        // 更新当前URL
        cachedUrl = currentUrl;

        // 如果是主页面,直接返回null
        if (currentUrl === 'https://live.douyin.com/' || currentUrl === 'https://live.douyin.com' ||
            currentUrl === 'https://www.douyin.com/follow' || currentUrl === 'https://www.douyin.com/follow/live') {
            // console.log('当前是直播主页面,不显示观看人数');
            cachedWebcastId = null;
            return null;
        }

        // 尝试匹配三种格式的URL
        // 格式1: https://live.douyin.com/613217711064
        // 格式2: https://live.douyin.com/613217711064?from_tab_name=main
        // 格式3: https://www.douyin.com/follow/live/574023227986
        const match = currentUrl.match(/\/([a-zA-Z0-9]+)(?:\?|$)/) || currentUrl.match(/\/live\/([a-zA-Z0-9]+)(?:\?|$)/);

        if (match) {
            if (match[1]==='self' || match[1]==='friend' || match[1]==='discover'){
                cachedWebcastId = null;
            }else{
                if(match[1].length>15){
                    cachedWebcastId = null;
                }else{
                    // console.log('找到直播间ID:', match[1]);
                    cachedWebcastId = match[1];
                    return cachedWebcastId;
                }

            }

        }

        // console.log('未找到直播间ID');
        cachedWebcastId = null;
        return null;
    }

    async function fetchViewerCount() {
        const webcastId = getWebcastId();
        if (!webcastId) {
            throw new Error('未找到直播间ID');
        }

        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: 'GET',
                url: `https://dyapi.phpnbw.com/get_live_room_num?webcast_id=${webcastId}&version=182`,
                timeout: 5000,
                onload: function(response) {
                    try {
                        const data = JSON.parse(response.responseText);
                        // 打印获取到的数据
                        // console.log('API Response:', data);
                        const viewerCount = data?.data?.data?.data?.[0]?.room_view_stats?.display_value || '未知';
                        // console.log('观看人数:', viewerCount); // 打印观看人数
                        resolve(viewerCount);
                    } catch (error) {
                        console.error('解析数据失败:', error);
                        reject(error);
                    }
                },
                onerror: function(error) {
                    console.error('请求失败:', error);
                    reject(error);
                },
                ontimeout: function() {
                    reject(new Error('请求超时'));
                }
            });
        });
    }

    function showViewerCount(count) {
        // 移除旧的显示元素(如果存在)
        const oldDisplay = document.getElementById('viewer-count-display');
        if (oldDisplay) {
            oldDisplay.remove();
        }

        // 创建显示元素,改用 a 标签
        const display = document.createElement('a');
        display.id = 'viewer-count-display';
        
        // 设置链接地址
        const webcastId = getWebcastId();
        display.href = `https://douyin.phpnbw.com/?id=${webcastId}`;
        
        // 添加悬浮提示
        display.title = '点击查看详细观看数据统计';
        
        // 添加新的样式
        display.style.cssText = `
            display: inline-block;
            background-color: rgba(0, 0, 0, 0.7);
            color: red;
            padding: 5px 10px;
            border-radius: 5px;
            font-size: 16px;
            z-index: 9999;
            text-decoration: none;
            cursor: pointer;
        `;
        
        if (count !== '未知' && count !== '获取失败') {
            display.textContent = `观看人数: ${count}`;
        }

        // 添加鼠标悬停效果
        display.addEventListener('mouseover', () => {
            display.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
            display.style.color = '#ff4444';
        });
        
        display.addEventListener('mouseout', () => {
            display.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
            display.style.color = 'red';
        });

        // 打开新标签页
        display.target = '_blank';

        // 剩余的定位代码保持不变
        const xpath = "/html/body/div[2]/div[2]/div/main/div[2]/div/div/div/pace-island/div/div/div[1]/div[1]";
        const targetElement = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

        if (targetElement) {
            targetElement.style.position = 'relative';
            display.style.marginLeft = '10px';
            targetElement.appendChild(display);
        } else {
            display.style.position = 'fixed';
            display.style.top = '75px';
            display.style.right = '50px';
            document.body.appendChild(display);
        }
    }

    async function updateViewerCount() {
        try {
            const count = await fetchViewerCount();
            showViewerCount(count);
        } catch (error) {
            console.error('获取观看人数失败:', error);
            showViewerCount('获取失败,请更新此插件');
        }
    }

    function init() {
        const url = window.location.href;
        // console.log('当前URL====================================:', url);
        // console.log('====================================');
        // 如果是主页面,直接返回,不执行任何操作
        if (url === 'https://live.douyin.com/' || url === 'https://live.douyin.com' ||  url ==='https://www.douyin.com/follow' ||
            url === 'https://www.douyin.com/follow/live' || url ==='https://www.douyin.com/discover' || url==='https://www.douyin.com/vs'
            || url==='https://www.douyin.com/series' || url==='https://www.douyin.com/recommend=1') {
            // console.log('当前是直播主页面,不显示观看人数1');
            return;
        }

        // 清除可能存在的旧定时器
        if (window.viewerCountTimer) {
            clearInterval(window.viewerCountTimer);
        }

        // 设置新的定时器并保存引用
        // console.log('开始初始化直播间观看人数显示');
        window.viewerCountTimer = setInterval(updateViewerCount, 4000);
        
        // 立即执行一次更新
        updateViewerCount();
    }

    // 页面加载完成后执行
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

    // URL 变化监听
    let lastUrl = location.href;
    new MutationObserver(() => {
        const url = location.href;
        if (url !== lastUrl) {
            lastUrl = url;
            console.log('URL changed, reinitializing...');
            init();
        }
    }).observe(document, {subtree: true, childList: true});
})();