小事化巨变,止于尝试始
抖音直播间在线人数突破10000+,原来可以如此简单
最近通过Electron开发了一个小工具,可以实时监控抖音用户粉丝人数变化!我做了一个小试验,在直播间通过这个工具监控"董宇辉"粉丝数数增量,结果几分钟时间直播间就突破了1万+,不得不感叹董宇辉丈母娘们力量强大。
我主要是通过Electron 结合抖音网页版用户详情页 开发了这个工具,它可以定时获取指定用户的粉丝数并实时显示在界面上。我在直播间通过屏幕分享这个实时在线人数增量的界面,一边和观众互动聊天,一边观察在线人数变化。大家看到在线人数持续增长都很兴奋,纷纷点赞、分享、观看,在线人数增速越来越快,很快就突破了1万大关。
通过这个实验,我发现,只要内容有吸引力,加上数据变化的即时反馈刺激,可以产生很强的爆发效应。我认为这种技术手段虽有些"作弊嫌疑",但对内容创作者而言也具有很强的指导意义。数据和互动是内容时代的关键,通过数字化手段优化内容传播效果,也是一种创新的尝试。
话不多说上代码:
抓取粉丝数量
ts
export async function dyh() {
// 1. 获取用户信息
const data = await fetch(
'https://www.douyin.com/user/MS4wLjABAAAAInYK7Wk_cCLwFlhAvpgeYFSXDQwUWmemBCsyCYtKOOI',
{
headers: {
accept:
'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
'cache-control': 'no-cache',
pragma: 'no-cache',
'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"macOS"',
'sec-fetch-dest': 'document',
'sec-fetch-mode': 'navigate',
'sec-fetch-site': 'none',
'sec-fetch-user': '?1',
'upgrade-insecure-requests': '1'
},
referrerPolicy: 'strict-origin-when-cross-origin',
body: null,
method: 'GET',
mode: 'cors',
credentials: 'include'
}
)
const text = await data.text()
// 2. 获取粉丝数
const parsed = /mplatformFollowersCount\":(\d+)/gi.exec(text)
if (parsed) return Number(parsed[1])
return 0
}
粉丝数量 就在页面中的mplatformFollowersCount
字段中,使用正则匹配粉丝数即可,如下图:
定时获取粉丝数量
ts
import { dfzx } from './dfzx'
import { dyh } from './dyh'
let dfzxCount = 0
let dyhCount = 0
let countdown = 0
let timer: NodeJS.Timeout
export async function polling(callback: (count: Douyin) => void) {
try {
const count = await dyh()
if (count > 0) dyhCount = count
} catch (e) {
console.error('getDyh', e)
}
try {
const count = await dfzx()
if (count > 0) dfzxCount = count
} catch (e) {
console.error('getDyh', e)
}
countdown = Math.floor(Math.random() * 26) + 5 // 随机生成5到30之间的整数
clearInterval(timer)
timer = setInterval(() => {
callback({
dyhCount,
dfzxCount,
countdown: countdown--
})
}, 1000)
setTimeout(() => polling(callback), countdown * 1000)
}
通信与渲染
Electron通信介绍:进程间通信 | Electron (electronjs.org)
流程图如下:一个渲染进程获取粉丝中,一个渲染进程用于最终数据的展示即可,主进程作为数据传递的中转站。
渲染进程一
抓取抖音数据,将数据发送至主进程。这里单开一个窗口用来处理在抖音页面上抓取数据的操作。
ts
import { polling } from './utils/polling'
window.addEventListener('DOMContentLoaded', () => {
if (window.location.hostname.includes('douyin')) {
void polling((data) => {
void ipcRenderer.invoke('douyin', data)
})
}
})
主进程
接收渲染进程一消息,发送至渲染进程二,作为最终显示的结果。
ts
import { ipcMain } from 'electron'
// douyinWindow1: 渲染进程一,是单独创建的一个窗口
type Douyin = {
dyhCount: number
dfzxCount: number
countdown: number
}
// 抖音
ipcMain.handle('douyin', (_, info: Douyin) => {
douyinWindow1.webContents.send('douyin', info)
})
渲染进程二
我们主要操作的进程,用来渲染 我们获取到的董宇辉粉丝数据
tsx
import { useDouyin } from '@renderer/store/douyin/hooks'
type UserInfo = {
name: string
avatar: string
followers: number
}
function User({ followers, name, avatar }: UserInfo) {
return (
<div className="p-2 flex flex-row gap-2 items-center">
<div className="relative avatar">
<div className="w-24 rounded-full">
<img src={avatar} alt="" />
</div>
<div className="absolute">
<span className="loading loading-ring loading-ring-lg text-green-500"></span>
</div>
</div>
<div className="flex flex-col gap-1">
<div className="text-[20px] text-white">{name}</div>
<div className="text-[22px] text-white/90">{`${followers / 10000}万`}</div>
</div>
</div>
)
}
function App() {
const { dyhCount, dfzxCount, countdown } = useDouyin()
return (
<div
style={{
backgroundSize: '100% 100%',
backgroundPosition: '0 0,100% 0',
backgroundRepeat: 'no-repeat',
backgroundImage:
'linear-gradient(90deg,rgba(26,28,39,0) 0%,#1a1c27 calc(100% - 852px),rgba(32,32,53,.35) 64.63%,rgba(33,33,57,.2) 100%),url(//lf3-cdn-tos.bytegoofy.com/obj/goofy/ies/douyin_web/media/dark_bg_default.51564fca60b7a3da.png)'
}}
className="h-screen"
>
<div className="fixed left-1/2 -translate-x-1/2 w-[375px] h-[70%] p-5 flex flex-col justify-center gap-3">
<User
name="董宇辉"
followers={dyhCount}
avatar="https://p3-pc.douyinpic.com/img/aweme-avatar/tos-cn-avt-0015_61ef8a9a0458c96eb5ff0afa94bab7fb~c5_300x300.jpeg?from=2956013662"
/>
<User
name="东方甄选"
followers={dfzxCount}
avatar="https://p3-pc.douyinpic.com/img/aweme-avatar/tos-cn-avt-0015_34583dc5dc55d5983f8a57fafcbceb6d~c5_300x300.jpeg?from=2956013662"
/>
<div className="text-white/50 pl-10">
自动刷新(<span className="text-white/30 text-sm">倒计时{countdown}秒</span>)
</div>
</div>
</div>
)
}
export default App
实际效果如下图:
接下来就可以去开播了...
还不会开播请接着往下看
开播流程
抖音直播伴侣了解一下:抖音直播伴侣 (douyin.com)
直播场景
添加素材 -> 选择窗口,选择开发的应用程序的窗口即可
直播画面
打开的开发好的应用程序,将其作为直播画面(如下图),被用户看到,我们可以在直播伴侣 中预览画面 ,预览之后同步画面 ,再点击开始直播,这样用户就能看到直播了
直播效果
小提示
直播的时候窗口比例是设置为
3:4
,在手机上显示效果比较好,但是如果我们开发的时候显示的内容完全撑满窗口,真正直播的时候,会导致内容显示不全 ,所以我们的内容不能完全撑满窗口,需要留有余地,以便适配不同宽度的手机
我的配置如下:
渲染进程的宽高配置
ts
const mainWindow = new BrowserWindow({
width: 457,
height: 812,
show: false,
autoHideMenuBar: true,
// 无边框
frame: false,
...(process.platform === 'linux' ? { icon } : {}),
webPreferences: {
preload: join(__dirname, '../preload/index.js'),
sandbox: false
},
resizable: false
})
我们将手机主要可视区域的宽度设置为 375px
,并居中显示,可以较好的适配手机画面,避免直播画面被裁切。
tsx
function App() {
return <div className="w-[375px] flex justify-center">主要内容显示区域</div>
}
董宇辉小作文
人生不会一直如你的愿,跌宕起伏才是人生
就像心跳一样,它是有高有低的
每当你觉得你是一个无名之辈,无足轻重
当你觉得未来黯淡无光时,请你记得
七千亿亿亿个原子,只为你一个而活
如果把你身体的DNA连成一条线
你可以从地球到冥王星
所以,你自己,就能完成星际穿越
不得不感叹,董宇辉丈母娘们确实厉害!!!