Greasy Fork

Greasy Fork is available in English.

洛曦 直播弹幕监听 转发至本地WS服务端

观察指定 DOM 节点的变化以将数据发送到连接的WebSocket服务端

当前为 2025-01-03 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         洛曦 直播弹幕监听 转发至本地WS服务端
// @namespace    http://tampermonkey.net/
// @version      0.13
// @description  观察指定 DOM 节点的变化以将数据发送到连接的WebSocket服务端
// @description  Github:https://github.com/Ikaros-521/AI-Vtuber/tree/main/Scripts/%E7%9B%B4%E6%92%ADws%E8%84%9A%E6%9C%AC
// @author       Ikaros
// @match        https://www.douyu.com/*
// @match        https://live.kuaishou.com/u/*
// @match        https://live.kuaishou.com/u/*
// @match        https://mobile.yangkeduo.com/*
// @match        https://live.1688.com/zb/play.html*
// @match        https://tbzb.taobao.com/live*
// @match        https://redlive.xiaohongshu.com/*
// @grant        none
// @namespace    http://greasyfork.icu/scripts/490966
// @license      GPL-3.0
// ==/UserScript==

(function () {
    "use strict";

    setTimeout(function () {
        let my_socket = null;
        let wsUrl = "ws://127.0.0.1:5001";
        let targetNode = null;
        let my_observer = null;

        const hostname = window.location.hostname;

        if (hostname === "www.douyu.com") {
            console.log("当前直播平台:斗鱼");
            wsUrl = "ws://127.0.0.1:5001";
        } else if (hostname === "live.kuaishou.com") {
            console.log("当前直播平台:快手");
            wsUrl = "ws://127.0.0.1:5001";
        } else if (hostname === "mobile.yangkeduo.com") {
            console.log("当前直播平台:拼多多");
            wsUrl = "ws://127.0.0.1:5001";
        } else if (hostname === "live.1688.com") {
            console.log("当前直播平台:1688");
            wsUrl = "ws://127.0.0.1:5001";
        } else if (hostname === "tbzb.taobao.com") {
            console.log("当前直播平台:淘宝");
            wsUrl = "ws://127.0.0.1:5001";
        } else if (hostname === "redlive.xiaohongshu.com") {
            console.log("当前直播平台:小红书");
            wsUrl = "ws://127.0.0.1:5001";
        }

        function connectWebSocket() {
            // 创建 WebSocket 连接,适配服务端
            my_socket = new WebSocket(wsUrl);

            // 当连接建立时触发
            my_socket.addEventListener("open", (event) => {
                console.log("ws连接打开");

                // 向服务器发送一条消息
                const data = {
                    type: "info",
                    content: "ws连接成功",
                };
                console.log(data);
                my_socket.send(JSON.stringify(data));
            });

            // 当收到消息时触发
            my_socket.addEventListener("message", (event) => {
                console.log("收到服务器数据:", event.data);
            });

            // 当连接关闭时触发
            my_socket.addEventListener("close", (event) => {
                console.log("WS连接关闭");

                // 重连
                setTimeout(() => {
                    connectWebSocket();
                }, 1000); // 延迟 1 秒后重连
            });
        }

        // 初始连接
        connectWebSocket();
        if (hostname === "www.douyu.com") {
            // 选择需要观察变化的节点
            targetNode = document.querySelector(".Barrage-list");

            // 创建观察器实例
            my_observer = new MutationObserver((mutations) => {
                mutations.forEach((mutation) => {
                    // 这里处理新增的DOM元素
                    if (mutation.type === "childList") {
                        mutation.addedNodes.forEach((node) => {
                            // 判断是否是新增的弹幕消息
                            if (node.classList.contains("Barrage-listItem")) {
                                // 新增的动态DOM元素处理
                                // console.log('Added node:', node);

                                const spans = node.getElementsByTagName("span");

                                let username = "";
                                let content = "";

                                for (let span of spans) {
                                    //console.log(span);
                                    if (span.classList.contains("Barrage-nickName")) {
                                        const targetSpan = span;
                                        // 获取用户名
                                        let tmp = targetSpan.textContent.trim().slice(0, -1);
                                        if (tmp != "")
                                            username = targetSpan.textContent.trim().slice(0, -1);
                                    } else if (span.classList.contains("Barrage-content")) {
                                        const targetSpan = span;
                                        // 获取弹幕内容
                                        content = targetSpan.textContent.trim();
                                    }
                                }

                                console.log(username + ":" + content);

                                // 获取到弹幕数据
                                if (username != "" && content != "") {
                                    const data = {
                                        type: "comment",
                                        username: username,
                                        content: content,
                                    };
                                    console.log(data);
                                    my_socket.send(JSON.stringify(data));
                                }
                            }
                        });
                    }
                });
            });
        } else if (hostname === "live.kuaishou.com") {
            // 选择需要观察变化的节点
            targetNode = document.querySelector(".chat-history");

            // 创建观察器实例
            my_observer = new MutationObserver((mutations) => {
                mutations.forEach((mutation) => {
                    console.log(mutation);
                    // console.log(mutation.type);
                    // 这里处理新增的DOM元素
                    if (mutation.type === "childList") {
                        mutation.addedNodes.forEach((node) => {
                            // 判断是否是新增的弹幕消息
                            if (node.classList.contains("wrapper") || node.classList.contains("item")) {
                                // 新增的动态DOM元素处理
                                console.log("Added node:", node);

                                const usernameElement = node.querySelector(".username");
                                const commentElement = node.querySelector(".comment");

                                // 礼物数据
                                const giftCommentElement = node.querySelector(".gift-comment");
                                const giftImgElement = node.querySelector(".gift-img");

                                const likeElement = node.querySelector(".like");

                                if (usernameElement && giftCommentElement) {
                                    // 礼物数据处理
                                    const username = usernameElement.textContent.trim();
                                    console.log(username + "送出了礼物");

                                    // 如果 my_socket 已经初始化,可以在这里发送礼物数据
                                    if (my_socket) {
                                        const data = {
                                            type: "gift",
                                            username: username,
                                            // 可以根据需要添加其他礼物相关数据
                                        };
                                        console.log(data);
                                        my_socket.send(JSON.stringify(data));
                                    }
                                } else if (usernameElement && likeElement) {
                                    const username = usernameElement.textContent.trim();
                                    console.log(username + "点了个赞");

                                    // 如果 my_socket 已经初始化,可以在这里发送礼物数据
                                    if (my_socket) {
                                        const data = {
                                            type: "like",
                                            username: username,
                                            // 可以根据需要添加其他礼物相关数据
                                        };
                                        console.log(data);
                                        my_socket.send(JSON.stringify(data));
                                    }
                                } else if (
                                    usernameElement &&
                                    commentElement &&
                                    !giftCommentElement &&
                                    !likeElement
                                ) {
                                    const username = usernameElement.textContent.trim().slice(0, -1);
                                    const content = commentElement.textContent.trim();

                                    console.log(username + ":" + content);

                                    // 获取到弹幕数据
                                    if (username !== "" && content !== "") {
                                        const data = {
                                            type: "comment",
                                            username: username,
                                            content: content,
                                        };
                                        console.log(data);
                                        // 如果 my_socket 已经初始化,可以在这里发送数据
                                        if (my_socket) {
                                            my_socket.send(JSON.stringify(data));
                                        }
                                    }
                                }
                            }
                        });
                    }
                });
            });
        } else if (hostname === "mobile.yangkeduo.com") {
            // 选择需要观察变化的节点
            targetNode = document.querySelector(".MYFlHgGu");

            // 创建观察器实例
            my_observer = new MutationObserver((mutations) => {
                mutations.forEach((mutation) => {
                    // 这里处理新增的DOM元素
                    if (mutation.type === "childList") {
                        mutation.addedNodes.forEach((node) => {
                            // 判断是否是新增的弹幕消息
                            if (node.classList.contains("_24Qh0Jmi")) {
                                // 新增的动态DOM元素处理
                                console.log("Added node:", node);

                                const usernameElement = node.querySelector(".t6fCgSnz");
                                const commentElement = node.querySelector("._16_fPXYP");

                                if (
                                    usernameElement &&
                                    commentElement
                                ) {
                                    const username = usernameElement.textContent.trim().slice(0, -1);
                                    const content = commentElement.textContent.trim();

                                    console.log(username + ":" + content);

                                    // 获取到弹幕数据
                                    if (username !== "" && content !== "") {
                                        const data = {
                                            type: "comment",
                                            username: username,
                                            content: content,
                                        };
                                        console.log(data);
                                        // 如果 my_socket 已经初始化,可以在这里发送数据
                                        if (my_socket) {
                                            my_socket.send(JSON.stringify(data));
                                        }
                                    }
                                }
                            }
                        });
                    }
                });
            });
        } else if (hostname === "live.1688.com") {
            // 选择需要观察变化的节点
            targetNode = document.querySelector(".pc-living-room-message");

            // 创建观察器实例
            my_observer = new MutationObserver((mutations) => {
                mutations.forEach((mutation) => {
                    // 这里处理新增的DOM元素
                    if (mutation.type === "childList") {
                        mutation.addedNodes.forEach((node) => {
                            // 判断是否是新增的弹幕消息
                            if (node.classList.contains("comment-message")) {
                                // 新增的动态DOM元素处理
                                console.log("Added node:", node);

                                const usernameElement = node.querySelector(".from");
                                const commentElement = node.querySelector(".msg-text");

                                if (
                                    usernameElement &&
                                    commentElement
                                ) {
                                    const username = usernameElement.textContent.trim().slice(0, -1);
                                    const content = commentElement.textContent.trim();

                                    console.log(username + ":" + content);

                                    // 获取到弹幕数据
                                    if (username !== "" && content !== "") {
                                        const data = {
                                            type: "comment",
                                            username: username,
                                            content: content,
                                        };
                                        console.log(data);
                                        // 如果 my_socket 已经初始化,可以在这里发送数据
                                        if (my_socket) {
                                            my_socket.send(JSON.stringify(data));
                                        }
                                    }
                                }
                            }
                        });
                    }
                });
            });
        } else if (hostname === "tbzb.taobao.com") {
            targetNode = document.querySelector("#liveComment");

            // 创建观察器实例
            my_observer = new MutationObserver((mutations) => {
                mutations.forEach((mutation) => {
                    // 这里处理新增的DOM元素
                    if (mutation.type === "childList") {

                        mutation.addedNodes.forEach((node) => {
                            // 判断是否是新增的弹幕消息
                            if (node.classList.contains("itemWrap--EcN_tFIg")) {
                                // 新增的动态DOM元素处理
                                console.log('Added node:', node);

                                const spans = node.getElementsByTagName("span");

                                let username = "";
                                let content = "";

                                for (let span of spans) {
                                    //console.log(span);
                                    if (span.classList.contains("authorTitle--_Dl75ZJ6")) {
                                        const targetSpan = span;
                                        // 获取用户名
                                        let tmp = targetSpan.textContent.trim().slice(0, -1);
                                        if (tmp != "")
                                            username = targetSpan.textContent.trim().slice(0, -1);
                                    } else if (span.classList.contains("content--pSjaTkyl")) {
                                        const targetSpan = span;
                                        // 获取弹幕内容
                                        content = targetSpan.textContent.trim();
                                    }
                                }

                                console.log(username + ":" + content);

                                // 获取到弹幕数据
                                if (username != "" && content != "") {
                                    const data = {
                                        type: "comment",
                                        username: username,
                                        content: content,
                                    };
                                    console.log(data);
                                    my_socket.send(JSON.stringify(data));
                                }
                            }
                        });
                    }
                });
            });
        } else if (hostname === "redlive.xiaohongshu.com") {
            // 选择需要观察变化的节点
            targetNode = document.querySelector(".comments");

            // 创建观察器实例
            my_observer = new MutationObserver((mutations) => {
                mutations.forEach((mutation) => {
                    console.log(mutation);
                    // console.log(mutation.type);
                    // 这里处理新增的DOM元素
                    if (mutation.type === "childList") {
                        mutation.addedNodes.forEach((node) => {
                            // 判断是否是新增的弹幕消息
                            if (node.classList.contains("comment-list-item")) {
                                // 新增的动态DOM元素处理
                                console.log("Added node:", node);

                                const spans = node.getElementsByTagName("span");

                                let live_tag = "";
                                let username = "";
                                let content = "";

                                console.log(spans.length);

                                for (let i = 0; i < spans.length; i++) {
                                    if (spans[i].classList.contains("live-tag")) {
                                        const targetSpan = spans[i];
                                        // 获取用户名
                                        let tmp = targetSpan.textContent.trim().slice(0, -1);
                                        if (tmp != "")
                                            live_tag = targetSpan.textContent.trim().slice(0, -1);
                                    }

                                    if (i == (spans.length - 2)) {
                                        const targetSpan = spans[i];
                                        // 获取用户名
                                        let tmp = targetSpan.textContent.trim().slice(0, -1);
                                        if (tmp != "")
                                            username = tmp;
                                    } else if (i == (spans.length - 1)) {
                                        const targetSpan = spans[i];
                                        // 获取弹幕
                                        let tmp = targetSpan.textContent.trim();
                                        if (tmp != "")
                                            content = tmp;
                                    }
                                }

                                console.log(username + ":" + content);

                                // 获取到弹幕数据
                                if (username != "" && content != "") {
                                    const data = {
                                        type: "comment",
                                        username: username,
                                        content: content,
                                    };
                                    console.log(data);
                                    my_socket.send(JSON.stringify(data));
                                }
                            }
                        });
                    }
                });
            });
        }

        // 配置观察选项
        const config = {
            childList: true,
            subtree: true,
        };

        try {
            // 开始观察
            my_observer.observe(targetNode, config);
        } catch (error) {
            console.error("观察失败:", error);
            setTimeout(() => {
                console.log("10S后尝试重新开始观察...");
                // 开始观察
                my_observer.observe(targetNode, config);
            }, 10000);
        }

    }, 10000);
})();