// ==UserScript==
// @name 获取直播弹幕
// @namespace http://tampermonkey.net/
// @version 2.2.0
// @description 在线获取弹幕
// @author 37
// @match https://buyin.jinritemai.com/*
// @match https://zs.kwaixiaodian.com/*
// @match https://liveplatform.taobao.com/*
// @match https://live.baidu.com/*
// @match https://live.pinduoduo.com/*
// @match https://live.bilibili.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=tampermonkey.net
// @grant none
// @license MIT
// @require http://libs.baidu.com/jquery/2.0.0/jquery.min.js
// @require https://cdn.staticfile.org/jquery/1.12.4/jquery.min.js
// ==/UserScript==
(function () {
"use strict";
let ws;
let observer;
let waitMsgList = [];
let stopWs = false;
let goodsListTikTok = []; //抖音商品存储
let goodsListKuShou = []; //快手商品存储
let getPopUpsContent = ""; //获取弹幕内容
let wxUrl = "";
let promotionsList = [];
let nowHost = window.location.host;
let ksBol = false;
let tbWscomments = [];
let tbOnceArr = [];
let tbOnceArrLastMsg = "";
let timeElment = "";
function connectWebSocket() {
ws = new WebSocket(wxUrl);
ws.addEventListener("open", () => {
if (nowHost == "zs.kwaixiaodian.com") {
ksBol = false;
$(".ReactVirtualized__List").scrollTop(9999);
setTimeout(() => {
ksBol = true;
}, 1000);
}
console.log("连接成功");
const submitButton = document.querySelector("#submitButton");
submitButton.textContent = `断开弹幕采集${
nowHost == "zs.kwaixiaodian.com" || "liveplatform.taobao.com"
? "(提示:连接弹幕后请勿手动拖动弹幕列表!)"
: ""
}`;
if (waitMsgList.length) {
//这里发送缓存也可以触发
waitMsgList.forEach((item) => {
ws.send(item);
console.log("成功发送缓存---", item);
//获取到用户发送的弹幕
getPopUpsContent = item;
console.log("获取关键弹幕", getPopUpsContent);
//匹配关键词
getKuShouKeyword(getPopUpsContent);
});
waitMsgList = [];
}
});
ws.addEventListener("message", (event) => {
console.log("从服务器接收到消息:", JSON.parse(event.data));
JSON.parse(event.data).type == 3 &&
getTikTokFindGoods(JSON.parse(event.data).answerText[0]);
});
ws.addEventListener("close", (event) => {
const submitButton = document.querySelector("#submitButton");
submitButton.textContent = "连接弹幕采集";
if (stopWs) {
stopWs = false;
} else {
setTimeout(() => {
console.log("WebSocket 已关闭--正在重新连接");
connectWebSocket(wxUrl);
}, 3000);
}
});
}
function startObserver() {
observer = new MutationObserver((mutationsList) => {
mutationsList.forEach((mutation) => {
mutation.addedNodes.forEach((addedNode) => {
var userElement = "";
var contentElement = "";
if (nowHost == "buyin.jinritemai.com") {
//抖音捕捉弹幕逻辑
if (
addedNode.nodeType === Node.ELEMENT_NODE &&
addedNode.classList.contains("index-module__commentItem___2fLb5")
) {
userElement = addedNode.querySelector(
".index-module__nickname___L6O_K"
);
contentElement = addedNode.querySelector(
".index-module__description___2W_id"
);
}
if (
addedNode.nodeType === Node.ELEMENT_NODE &&
addedNode.classList.contains(
"index-module__newCommentShadow___3rffn"
)
) {
console.log("监测到需要加载新弹幕");
$(".index-module__newCommentShadow___3rffn")[0].click();
}
}
if (nowHost == "zs.kwaixiaodian.com") {
//快手捕捉弹幕逻辑(快手中控有后台监测,需手动活跃到可视窗口)
if (!ksBol) return; //等待滚动条加载
try {
if (
addedNode.nodeType === Node.ELEMENT_NODE &&
addedNode.childNodes.length &&
addedNode.childNodes[0].classList.contains("list-item--TAlkJ")
) {
userElement = addedNode.querySelector(".username--BCJbc");
contentElement = addedNode.querySelector(
".replied-content--Mq1R1"
);
}
} catch (error) {}
if (
addedNode.nodeType === Node.ELEMENT_NODE &&
addedNode.classList.contains("bubble--OQEn3")
) {
try {
$(".bubble--OQEn3")[0].click();
} catch (error) {
// console.log(error)
}
}
}
if (nowHost == "liveplatform.taobao.com") {
//淘宝捕捉弹幕逻辑
// console.log('------进入淘宝-----');
if (
addedNode.nodeType === Node.ELEMENT_NODE &&
addedNode.classList.contains("tc-comment-item")
) {
userElement = addedNode.querySelector(
".tc-comment-item-userinfo-name "
);
contentElement = addedNode.querySelector(
".tc-comment-item-content span"
);
timeElment = addedNode
.querySelector(".alpw-comment-time")
.textContent.trim();
tbWscomments.push({
userName: userElement.textContent,
answerText: contentElement.textContent,
timestamp: timeElment,
});
tbOnceArr = tbWscomments.filter((value, index, self) => {
return (
index ===
self.findIndex(
(item) =>
item.userName === value.userName &&
item.answerText === value.answerText
)
);
});
//当前时间
const currentTime = new Date();
const fiveMinutesBefore = new Date(
currentTime.getTime() - 5 * 60 * 1000
);
const fiveMinutesAfter = new Date(
currentTime.getTime() + 5 * 60 * 1000
);
tbOnceArr = tbOnceArr.filter((item) => {
const itemTimestamp = new Date().setHours(
item.timestamp.substring(0, 2),
item.timestamp.substring(3, 5),
0
);
return (
itemTimestamp >= fiveMinutesBefore &&
itemTimestamp <= fiveMinutesAfter
);
});
// console.log(tbWscomments, tbOnceArr,timeElment,'淘宝消息');
}
//如果有需要加载的提示
var element = $(".tc-comment-list-newtip");
// 判断特定条件
if (element.css("display") === "block") {
element.trigger("click");
element.click(function () {});
}
}
if (nowHost == "live.baidu.com") {
//百度捕捉弹幕逻辑
console.log("进入百度弹幕");
if (
addedNode.nodeType === Node.ELEMENT_NODE &&
addedNode.classList.contains("msg-box")
) {
userElement = addedNode.querySelector(".msg-box-name");
contentElement = addedNode.querySelector(".msg-box-text");
}
}
if (nowHost == "live.pinduoduo.com") {
//拼多多捕捉弹幕逻辑
console.log("进入pdd弹幕");
if (
addedNode.nodeType === Node.ELEMENT_NODE &&
addedNode.classList.contains("msg-wrap")
) {
userElement = addedNode.querySelector(".author");
contentElement = addedNode.querySelector(".content");
}
}
if (nowHost == "live.bilibili.com") {
//b站捕捉弹幕逻辑
console.log("进入b站弹幕");
if (
addedNode.nodeType === Node.ELEMENT_NODE &&
addedNode.classList.contains("chat-item")
) {
userElement = addedNode.querySelector(".user-name");
contentElement = addedNode.querySelector(".danmaku-item-right");
}
}
//发送弹幕 在发送弹幕这里做弹幕关键词对比,然后触发上架购物车按钮
if (contentElement) {
if (
nowHost == "liveplatform.taobao.com" &&
tbOnceArr.length !== 0
) {
if (
tbOnceArr[tbOnceArr.length - 1].answerText !== tbOnceArrLastMsg
) {
const dataToSend = {
answerText: tbOnceArr[tbOnceArr.length - 1].answerText,
type: 1,
};
if (ws && ws.readyState === 1) {
tbOnceArrLastMsg = tbOnceArr[tbOnceArr.length - 1].answerText;
ws.send(JSON.stringify(dataToSend));
console.log(
"成功发送弹幕---",
tbOnceArr[tbOnceArr.length - 1].userName,
tbOnceArr[tbOnceArr.length - 1].answerText
);
} else {
tbOnceArrLastMsg = tbOnceArr[tbOnceArr.length - 1].answerText;
console.log(
"储存弹幕一条---",
tbOnceArr[tbOnceArr.length - 1].userName,
tbOnceArr[tbOnceArr.length - 1].answerText
);
waitMsgList.push(JSON.stringify(dataToSend));
}
}
} else if (nowHost != "liveplatform.taobao.com") {
console.log("进入别的平台");
const dataToSend = {
answerText: contentElement.textContent,
type: 1,
};
if (ws && ws.readyState === 1) {
ws.send(JSON.stringify(dataToSend));
//获取到用户发送的弹幕
getPopUpsContent = contentElement.textContent;
console.log(
"成功发送弹幕---",
userElement.textContent,
contentElement.textContent
);
console.log("获取关键弹幕1", getPopUpsContent);
//匹配关键词
getKuShouKeyword(getPopUpsContent);
} else {
waitMsgList.push(JSON.stringify(dataToSend));
console.log(
"储存弹幕一条---",
userElement.textContent,
contentElement.textContent
);
}
}
}
});
});
});
observer.observe(document.documentElement, {
childList: true,
subtree: true,
});
}
//抖音获取和查找商品
function getTikTokGoodsList() {
const match = wxUrl.match(/websocket\/([^\/]+)/);
if (match ? match[1] : null) {
$.ajax({
type: "GET",
url: "https://buyin.jinritemai.com/api/anchor/livepc/promotions",
success: function (data) {
promotionsList = data.data.promotions;
goodsListTikTok = data.data.promotions.map((data, index) => {
return {
goodName: data.title,
goodNo: index + 1,
price: data.min_price / 100,
liveId: match[1],
};
});
const dataToSend = {
answerText: goodsListTikTok,
type: 4,
};
ws.send(JSON.stringify(dataToSend));
alert("更新商品成功");
},
});
} else {
console.log("获取liveID失败");
}
}
function getTikTokFindGoods(item) {
$.ajax({
type: "POST",
url: "https://buyin.jinritemai.com/api/anchor/livepc/setcurrent",
data: { version: promotionsList[item.goodNo - 1].promotion_id },
success: function (data) {
document.querySelectorAll(".index__actionItem___2Z8YV")[1].click();
},
});
}
//快手获取和查找商品
function getKuShouGoodsList() {
const match = wxUrl.match(/websocket\/([^\/]+)/);
if (match ? match[1] : null) {
$.ajax({
type: "post",
url: "https://zs.kwaixiaodian.com/rest/pc/live/assistant/dynamic/onsale",
data: { version: 2 },
success: function (data) {
let liveStreamId = data.data.liveStreamId;
goodsListKuShou = data.data.commodityCardList.map((data, index) => {
return {
goodName: data.title,
goodNo: index + 1,
price: data.originalPrice.price,
itemId: data.commodityId,
liveStreamId: liveStreamId,
};
});
const dataToSend = {
answerText: goodsListKuShou,
type: 4,
};
ws.send(JSON.stringify(dataToSend));
alert("更新商品成功");
console.log(goodsListKuShou);
},
});
} else {
console.log("获取liveID失败");
}
}
//快手弹幕关键字
// 使用 RegExp.escape() 转义特殊字符(假设已实现)
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
}
function getKuShouKeyword(userRemark) {
console.log(userRemark, "用户弹幕");
// 转义后的关键词用于创建正则表达式
const escapedKeyword = escapeRegExp(userRemark);
const keywordRegex = new RegExp(escapedKeyword, "i"); // 使用/i标志实现不区分大小写的匹配
goodsListKuShou.forEach((item) => {
const findGoods = keywordRegex.test(item.goodName);
console.log(findGoods);
if (findGoods) {
getKuShouShelveApi(item.itemId, item.liveStreamId);
return;
}
});
}
//快手上架api
function getKuShouShelveApi(
itemId = 21803314703569,
liveStreamId = "12239880278"
) {
$.ajax({
type: "post",
url: "https://zs.kwaixiaodian.com/rest/pc/live/assistant/shopCar/record/start",
data: JSON.stringify({ liveStreamId, itemId }),
dataType: "json",
headers: {
"Content-Type": "application/json", // 明确设置Content-Type为JSON
},
success: function (data) {
console.log(data, "快手数据");
},
error: function (xhr, status, error) {
// 增加了错误处理,以便在请求失败时记录错误
console.error(`请求失败: ${status} ${error}`);
},
});
}
function stopObserver() {
if (observer) {
observer.disconnect();
observer = null;
}
}
function disconnectWebSocket() {
if (ws) {
ws.close();
stopObserver();
stopWs = true;
console.log("WebSocket 已手动断开连接");
}
}
function createFloatingInput() {
const inputContainer = document.createElement("div");
inputContainer.style.position = "fixed";
inputContainer.style.top = "60px";
inputContainer.style.left = "20px";
inputContainer.style.zIndex = "999999";
const inputElement = document.createElement("input");
inputElement.setAttribute("type", "text");
inputElement.setAttribute("placeholder", "输入 WebSocket 地址");
inputElement.classList.add("input-box");
inputElement.style.padding = "8px";
inputElement.style.border = "1px solid #ccc";
inputElement.style.borderRadius = "4px";
inputElement.style.outline = "none";
const submitButton = document.createElement("button");
submitButton.id = "submitButton";
submitButton.textContent = "连接弹幕采集";
submitButton.style.marginLeft = "8px";
submitButton.style.padding = "8px";
submitButton.style.border = "1px solid #ccc";
submitButton.style.borderRadius = "4px";
submitButton.style.backgroundColor = "#f0f0f0";
submitButton.style.cursor = "pointer";
const goodsButton = document.createElement("button");
goodsButton.id = "submitButton";
goodsButton.textContent = "更新商品";
goodsButton.style.marginLeft = "8px";
goodsButton.style.padding = "8px";
goodsButton.style.border = "1px solid #ccc";
goodsButton.style.borderRadius = "4px";
goodsButton.style.backgroundColor = "#f0f0f0";
goodsButton.style.cursor = "pointer";
submitButton.addEventListener("click", () => {
const inputVal = inputElement.value.trim();
if (inputVal) {
if (ws && ws.readyState == 1) {
disconnectWebSocket();
} else {
startObserver(); //捕捉弹幕的逻辑
wxUrl = inputVal; //点击连接后,将抓取弹幕的websockte赋值给它
connectWebSocket(inputVal);
}
}
});
//点击更新商品btn执行下面的函数
goodsButton.addEventListener("click", () => {
if (nowHost == "buyin.jinritemai.com") {
getTikTokGoodsList();
} else if (nowHost == "zs.kwaixiaodian.com") {
getKuShouGoodsList();
} else {
alert("还在开发中");
}
});
inputContainer.appendChild(inputElement);
inputContainer.appendChild(submitButton);
inputContainer.appendChild(goodsButton);
document.body.appendChild(inputContainer);
}
createFloatingInput();
})();