目录

1.服务端提供所有直播间的列表信息

2.前端显示房间列表

3.创建房间

1.服务端提供所有直播间的列表信息

1.marshmallow.py

from marshmallow_sqlalchemy import SQLAlchemyAutoSchema,auto_field
from .models import LiveStream,db
from application.apps.users.models import User
from marshmallow import post_dump
class StreamInfoSchema(SQLAlchemyAutoSchema):
id = auto_field()
name = auto_field()
room_name = auto_field()
user = auto_field() class Meta:
model = LiveStream
include_fk = True
include_relationships = True
fields = ["id","name","room_name","user"]
sql_session = db.session @post_dump()
def user_format(self, data, **kwargs):
user = User.query.get(data["user"])
if user is None:
return data data["user"] = {
"id":user.id,
"nickname": user.nickname if user.nickname else "",
"ip": user.ip_address if user.ip_address else "",
"avatar": user.avatar if user.avatar else ""
}
return data

marshmallow.py

2.views.py

from .marshmallow import StreamInfoSchema
from flask import current_app
@jsonrpc.method("Live.stream.list")
@jwt_required # 验证jwt
def list_stream():
# 验证登陆用户信息
current_user_id = get_jwt_identity() # get_jwt_identity 用于获取载荷中的数据
user = User.query.get(current_user_id)
if user is None:
return {
"errno": status.CODE_NO_USER,
"errmsg": message.user_not_exists,
"data": { }
} # 查询数据库中所有的直播流
stream_list = LiveStream.query.filter(LiveStream.status==True, LiveStream.is_deleted==False).all()
sis = StreamInfoSchema()
data_list = sis.dump(stream_list,many=True) # 使用requests发送get请求,读取当前srs中所有的直播流和客户端列表
import requests,re,json
stream_response = requests.get(current_app.config["SRS_HTTP_API"]+"streams/")
client_response = requests.get(current_app.config["SRS_HTTP_API"]+"clients/")
stream_text = re.sub(r'[^\{\}\/\,0-9a-zA-Z\"\'\:\[\]\._]', "", stream_response.text)
client_text = re.sub(r'[^\{\}\/\,0-9a-zA-Z\"\:\[\]\._]', "", client_response.text)
stream_dict = json.loads(stream_text)
client_dict = json.loads(client_text) # 在循环中匹配所有的客户端对应的总人数和当前推流用户的IP地址
for data in data_list:
data["status"] = False
for stream in stream_dict["streams"]:
if data["name"] == stream["name"]:
data["status"] = stream["publish"]["active"]
break
data["clients_number"] = 0
for client in client_dict["clients"]:
if data["name"] == client["url"].split("/")[-1]:
data["clients_number"]+=1
if client["publish"] and "/live/"+data["name"]==client["url"]:
data["user"]["ip"] = client["ip"]
return {
"errno": status.CODE_OK,
"errmsg": message.ok,
"stream_list": data_list
}

views.py

2.前端显示房间列表

1.房间列表页面初始化:live_list.html

把上面的客户端live_list.html,修改成live.html,并新建live_list.html,代码:

<!DOCTYPE html>
<html>
<head>
<title>好友列表</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
</head>
<body>
<div class="app setting" id="app">
<div class="bg">
<img src="../static/images/rooms_bg.png">
</div>
<img class="back" @click="goto_home" src="../static/images/user_back.png" alt="">
<div class="add_friend_btn" @click="add_room">
<img src="../static/images/add_room.png" alt="">
</div>
<div class="friends_list room_list">
<div class="item" v-for="room in rooms">
<div class="avatar">
<img class="user_avatar" :src="room.avatar" alt="">
</div>
<div class="info">
<p class="username">{{room.name}}</p>
<p class="fruit">人数:{{room.num}}</p>
</div>
<div class="behavior pick">直播</div>
<div class="goto"><img src="../static/images/arrow1.png" alt=""></div>
</div>
</div>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
rooms:[{"avatar":"../static/images/avatar.png",name:"房间名称",num:5}],
prev:{name:"",url:"",params:{}},
current:{name:"live",url:"live_list.html",params:{}},
}
},
created(){ },
methods:{
add_room(){ },
goto_home(){
// 退出当前页面
this.game.outFrame("live","live_list.html", this.current);
},
}
});
}
</script>
</body>
</html>

房间列表页面初始化:live_list.html

2.房间列表页面CSS样式

.room_list{
position: absolute;
top: 18rem;
}

3.前端获取后端传过来的直播流列表:get_room_list

获取服务端的直播流列表, live_list代码:

<!DOCTYPE html>
<html>
<head>
<title>房间列表</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
</head>
<body>
<div class="app user setting" id="app">
<div class="bg">
<img src="../static/images/rooms_bg.png">
</div>
<img class="back" @click="goto_home" src="../static/images/user_back.png" alt="">
<div class="add_friend_btn" @click="add_room">
<img src="../static/images/add_room.png" alt="">
</div>
<div class="friends_list room_list">
<div class="item" v-for="room in rooms">
<div class="avatar">
<img class="user_avatar" :src="room.user && settings.static_url+room.user.avatar" alt="">
</div>
<div class="info">
<p class="username">{{room.room_name}}</p>
<p class="fruit">人数:{{room.clients_number}}</p>
</div>
<div class="behavior pick" v-if="room.status">直播</div>
<div class="goto" @click="goto_live(room.id,room.name)"><img src="../static/images/arrow1.png" alt=""></div>
</div>
</div>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
rooms:[], // 房间列表
prev:{name:"",url:"",params:{}},
current:{name:"live",url:"live_list.html",params:{}},
}
},
created(){
this.get_room_list();
},
methods:{
get_room_list(){
var token = this.game.get("access_token") || this.game.fget("access_token");
this.axios.post("",{
"jsonrpc": "2.0",
"id": this.uuid(),
"method": "Live.stream.list",
"params": {}
},{
headers:{
Authorization: "jwt " + token,
}
}).then(response=>{
if(parseInt(response.data.result.errno)==1000){
this.rooms = response.data.result.stream_list;
}else{
this.game.print(response.data.result.errmsg);
}
}).catch(error=>{
// 网络等异常
this.game.print(error);
});
},
goto_live(room_id,stream_name){
// 进入房间
var pageParam = {
name: this.current.name,
url: this.current.url,
room_id: room_id,
stream_name: stream_name
}
this.game.goFrame("room","live.html",pageParam);
},
add_room(){ },
goto_home(){
// 退出当前页面
this.game.outWin("live");
},
}
});
}
</script>
</body>
</html>

前端获取后端传过来的直播流列表

3.创建房间

1.创建房间页面初始化:add_room.html

当用户点击创建房间时,会让用户输入房间名和房间密码

当用户输入后点击确定,会向后端接口发送请求,将用户输入的房间名和房间密码传递给后端

创建房间, add_room.html, 代码:

<!DOCTYPE html>
<html>
<head>
<title>创建房间</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
</head>
<body>
<div class="app frame avatar update_password" id="app">
<div class="box">
<p class="title">创建房间</p>
<img class="close" @click="close_frame" src="../static/images/close_btn1.png" alt="">
<div class="content">
<input class="password" type="text" v-model="name" placeholder="房间名称....">
<input class="password password2" type="password" v-model="password" placeholder="房间密码....">
</div>
<img @click="add_room_submit" class="btn" src="../static/images/yes.png" alt="">
</div>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
name:"",
password:"",
prev:{name:"",url:"",params:{}},
current:{name:"add_room",url:"add_room.html",params:{}},
}
},
methods:{
close_frame(){
this.game.outFrame("add_room");
},
add_room_submit(){
// 提交数据
var token = this.game.get("access_token") || this.game.fget("access_token");
this.axios.post("",{
"jsonrpc": "2.0",
"id": this.uuid(),
"method": "Live.stream",
"params": {
room_name: this.name,
password: this.password
}
},{
headers:{
Authorization: "jwt " + token,
}
}).then(response=>{
if(parseInt(response.data.result.errno)==1000){
this.rooms = response.data.result.stream_list;
}else{
this.game.print(response.data.result.errmsg);
}
}).catch(error=>{
// 网络等异常
this.game.print(error);
});
},
}
});
}
</script>
</body>
</html>

创建房间页面初始化:add_room.html

2.在直播流数据表中增加房间密码字段

服务端接口增加房间密码字段,live/models.py ,代码:

from application.utils.models import BaseModel,db
class LiveStream(BaseModel):
"""直播流管理"""
__tablename__ = "mf_live_stream"
name = db.Column(db.String(255), unique=True, comment="流名称")
room_name = db.Column(db.String(255), default="未命名",comment="房间名称")
room_password = db.Column(db.String(255), default="", comment="房间密码")
user = db.Column(db.Integer, comment="房主") class LiveRoom(BaseModel):
"""直播间"""
__tablename__ = "mf_live_room"
stream_id = db.Column(db.Integer, comment="直播流ID")
user = db.Column(db.Integer, comment="用户ID")

3.后端修改创建房间接口,新增验证密码功能

服务端创建房间接口, 新增密码字段并验证密码才可以进入房间

用户输入房间名和房间密码后,前端向后端发起请求,将输入内容提交给后端

后端接收到房间名和房间密码后,做如下几件事:

1.创建直播流:,mysql中存放:用户id/房间名/房间密码/直播流号

2.创建房间:mysql中存放:用户id/直播流号

live/views.py, 代码:

from application import jsonrpc,db
from message import ErrorMessage as message
from status import APIStatus as status
from flask_jwt_extended import jwt_required,get_jwt_identity
from application.apps.users.models import User
from .models import LiveStream,LiveRoom
from datetime import datetime
import random
@jsonrpc.method("Live.stream")
@jwt_required # 验证jwt
def live_stream(room_name,password):
"""创建直播流"""
current_user_id = get_jwt_identity() # get_jwt_identity 用于获取载荷中的数据
user = User.query.get(current_user_id)
if user is None:
return {
"errno": status.CODE_NO_USER,
"errmsg": message.user_not_exists,
}
# 申请创建直播流
stream = LiveStream.query.filter(LiveStream.user==user.id).first()
if stream is None:
stream_name = "room_%06d%s%06d" % (
user.id, datetime.now().strftime("%Y%m%d%H%M%S"), random.randint(100, 999999))
stream = LiveStream(
name=stream_name,
user=user.id,
room_name=room_name,
room_password=password
)
db.session.add(stream)
db.session.commit()
else:
stream.room_name = room_name
stream.room_password = password
db.session.commit() # 进入房间
room = LiveRoom.query.filter(LiveRoom.user==user.id,LiveRoom.stream_id==stream.id).first()
if room is None:
room = LiveRoom(
stream_id=stream.id,
user=user.id
)
db.session.add(room)
db.session.commit() return {
"errno": status.CODE_OK,
"errmsg": message.ok,
"data":{
"stream_name": stream.name,
"room_name": room_name,
"room_owner": user.id,
"room_id": "%04d" % stream.id,
}
} from .marshmallow import StreamInfoSchema
from flask import current_app
@jsonrpc.method("Live.stream.list")
@jwt_required # 验证jwt
def list_stream():
"""房间列表"""
current_user_id = get_jwt_identity() # get_jwt_identity 用于获取载荷中的数据
user = User.query.get(current_user_id)
if user is None:
return {
"errno": status.CODE_NO_USER,
"errmsg": message.user_not_exists,
"data": { }
} stream_list = LiveStream.query.filter(LiveStream.status==True, LiveStream.is_deleted==False).all()
sis = StreamInfoSchema()
data_list = sis.dump(stream_list,many=True) # 使用requests发送get请求
import requests
stream_response = requests.get(current_app.config["SRS_HTTP_API"]+"streams/")
client_response = requests.get(current_app.config["SRS_HTTP_API"]+"clients/")
import re,json
stream_text = re.sub(r'[^\{\}\/\,0-9a-zA-Z\"\'\:\[\]\._]', "", stream_response.text)
client_text = re.sub(r'[^\{\}\/\,0-9a-zA-Z\"\:\[\]\._]', "", client_response.text)
stream_dict = json.loads(stream_text)
client_dict = json.loads(client_text)
for data in data_list:
data["status"] = False
for stream in stream_dict["streams"]:
if data["name"] == stream["name"]:
data["status"] = stream["publish"]["active"]
break
data["clients_number"] = 0
for client in client_dict["clients"]:
if data["name"] == client["url"].split("/")[-1]:
data["clients_number"]+=1
if client["publish"] and "/live/"+data["name"]==client["url"]:
data["user"]["ip"] = client["ip"]
return {
"errno": status.CODE_OK,
"errmsg": message.ok,
"stream_list": data_list
}

服务端提供创建房间接口

4.前端判断房间是否存在密码,如存在密码必须正确输入密码才可进入房间

客户端中判定当房间存在密码时, 用户必须输入密码成功以后才可以进入房间, live_list.html代码:

<!DOCTYPE html>
<html>
<head>
<title>房间列表</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
</head>
<body>
<div class="app user setting" id="app">
<div class="bg">
<img src="../static/images/rooms_bg.png">
</div>
<img class="back" @click="goto_home" src="../static/images/user_back.png" alt="">
<div class="add_friend_btn" @click="add_room">
<img src="../static/images/add_room.png" alt="">
</div>
<div class="friends_list room_list">
<div class="item" v-for="room in rooms" @click="goto_live(room.id,room.name,room.room_password)">
<div class="avatar">
<img class="user_avatar" :src="room.user && settings.static_url+room.user.avatar" alt="">
</div>
<div class="info">
<p class="username">{{room.room_name}}</p>
<p class="fruit">人数:{{room.clients_number}}</p>
</div>
<div class="behavior pick" v-if="room.status">直播</div>
<div class="goto"><img src="../static/images/arrow1.png" alt=""></div>
</div>
</div>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
rooms:[], // 房间列表
prev:{name:"",url:"",params:{}},
current:{name:"live",url:"live_list.html",params:{}},
}
},
created(){
this.get_room_list();
},
methods:{
get_room_list(){
var token = this.game.get("access_token") || this.game.fget("access_token");
this.axios.post("",{
"jsonrpc": "2.0",
"id": this.uuid(),
"method": "Live.stream.list",
"params": {}
},{
headers:{
Authorization: "jwt " + token,
}
}).then(response=>{
if(parseInt(response.data.result.errno)==1000){
this.rooms = response.data.result.stream_list;
}else{
this.game.print(response.data.result.errmsg);
}
}).catch(error=>{
// 网络等异常
this.game.print(error);
});
},
goto_live(room_id,stream_name,room_password){
// 验证密码
if(room_password != null){
api.prompt({
title:"请输入房间密码!",
buttons: ['确定', '取消'],
}, (ret, err)=>{
if( ret.text == room_password ){
this.goto_room(room_id,stream_name);
}else {
alert("密码错误!");
}
});
}else{
this.goto_room(room_id,stream_name);
}
},
goto_room(room_id,stream_name){
// 进入房间
var pageParam = {
name: this.current.name,
url: this.current.url,
room_id: room_id,
stream_name: stream_name
}
this.game.goFrame("room","live.html",pageParam);
},
add_room(){
this.game.goFrame("add_room","add_room.html",this.current,null,{
type:"push",
subType:"from_top",
duration:300
}); api.addEventListener({
name: 'add_room_success'
}, (ret, err)=>{
if( ret ){
this.game.print("创建房间成功");
}
}); },
goto_home(){
// 退出当前页面
this.game.outWin("live");
},
}
});
}
</script>
</body>
</html>

前端判断房间是否存在密码,如果存在密码,必须正确输入密码才可以进入房间

5.当用户点击返回键时,关闭推流

1.live_list.html

监听当前窗口下的任意一个帧页面点击返回键(keyback)的操作

当用户点击返回键的时候,告知(sendEvent)直播间关闭直播推流

<!DOCTYPE html>
<html>
<head>
<title>房间列表</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
</head>
<body>
<div class="app user setting" id="app">
<div class="bg">
<img src="../static/images/rooms_bg.png">
</div>
<img class="back" @click="goto_home" src="../static/images/user_back.png" alt="">
<div class="add_friend_btn" @click="add_room">
<img src="../static/images/add_room.png" alt="">
</div>
<div class="friends_list room_list">
<div class="item" v-for="room in rooms" @click="goto_live(room.id,room.name,room.room_password)">
<div class="avatar">
<img class="user_avatar" :src="room.user && settings.static_url+room.user.avatar" alt="">
</div>
<div class="info">
<p class="username">{{room.room_name}}</p>
<p class="fruit">人数:{{room.clients_number}}</p>
</div>
<div class="behavior pick" v-if="room.status">直播</div>
<div class="goto"><img src="../static/images/arrow1.png" alt=""></div>
</div>
</div>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
rooms:[], // 房间列表
prev:{name:"",url:"",params:{}},
current:{name:"live",url:"live_list.html",params:{}},
}
},
created(){
this.get_room_list();
},
methods:{
get_room_list(){
var token = this.game.get("access_token") || this.game.fget("access_token");
this.axios.post("",{
"jsonrpc": "2.0",
"id": this.uuid(),
"method": "Live.stream.list",
"params": {}
},{
headers:{
Authorization: "jwt " + token,
}
}).then(response=>{
if(parseInt(response.data.result.errno)==1000){
this.rooms = response.data.result.stream_list;
}else{
this.game.print(response.data.result.errmsg);
}
}).catch(error=>{
// 网络等异常
this.game.print(error);
});
},
goto_live(room_id,stream_name,room_password){
// 验证密码
if(room_password != null){
api.prompt({
title:"请输入房间密码!",
buttons: ['确定', '取消'],
}, (ret, err)=>{
if( ret.text == room_password ){
this.goto_room(room_id,stream_name);
}else {
alert("密码错误!");
}
});
}else{
this.goto_room(room_id,stream_name);
}
},
goto_room(room_id,stream_name){
// 进入房间
var pageParam = {
name: this.current.name,
url: this.current.url,
room_id: room_id,
stream_name: stream_name
}
// 当用户在当前窗口下的任何一个帧页面中点击返回键,发起全局通知
api.addEventListener({
name: 'keyback'
}, (ret, err)=>{
// 告知直播间,关闭直播推流
api.sendEvent({
name: 'live_page_out',
extra: { }
});
}); this.game.goFrame("room","live.html",pageParam);
},
add_room(){
this.game.goFrame("add_room","add_room.html",this.current,null,{
type:"push",
subType:"from_top",
duration:300
}); api.addEventListener({
name: 'add_room_success'
}, (ret, err)=>{
if( ret ){
this.game.print("创建房间成功");
// 进入房间
this.goto_room(ret.value.room_id,ret.value.stream_name);
}
}); },
goto_home(){
// 退出当前页面
this.game.outWin("live");
},
}
});
}
</script>
</body>
</html>

live_list.html监听退出动作,并告知直播间关闭直播推流

2.live.html

监听用户是否有返回的动作,如果监听到,关闭摄像头采集功能和直播推流

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="format-detection" content="telephone=no,email=no,date=no,address=no">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
</head>
<body>
<div class="app" id="app">
<br><br><br><br>
<br><br><br><br>
<button @click="start_live">我要开播</button>
<button @click="viewer">我是观众</button>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
music_play:true, //
stream_name:"", // 直播流名称
prev:{name:"",url:"",params:{}}, //
current:{name:"live",url:"live_list.html","params":{}}, //
}
},
created(){
this.stream_name = api.pageParam.stream_name;
},
methods:{
viewer(){
// 观看直播
var obj = api.require('playModule');
obj.play({
rect:
{ x: 0,
y : 0,
w : 360,
h: 1080,
},
fixedOn: api.frameName,
title: 'test',
scalingMode:2,
url: this.settings.live_stream_server+this.stream_name,
defaultBtn: false,
enableFull : false,
isTopView : false,
isLive: true,
placeholderText:true,
}, (ret, err)=>{
this.game.print(ret);
});
},
liver(){
var token = this.game.get("access_token") || this.game.fget("access_token");
this.axios.post("",{
"jsonrpc": "2.0",
"id": this.uuid(),
"method": "Live.stream",
"params": {
"room_name": "爱的直播间"
}
},{
headers:{
Authorization: "jwt " + token,
}
}).then(response=>{
var message = response.data.result;
if(parseInt(message.errno)==1005){
this.game.goWin("user","login.html", this.current);
}
if(parseInt(message.errno)==1000){
this.stream_name = message.data.stream_name;
this.game.print(this.stream_name)
}else{
this.game.print(response.data);
}
}).catch(error=>{
// 网络等异常
this.game.print(error);
});
},
start_live(){
// 开始直播
var acLive = api.require('acLive');
// 打开摄像头采集视频信息
acLive.open({
camera:0, // 1为前置摄像头, 0为后置摄像头,默认1
rect : { // 采集画面的位置和尺寸
x : 0,
y : 0,
w : 360,
h : 1080,
}
},(ret, err)=>{
this.game.print(ret);
// 开启美颜
acLive.beautyFace();
// 开始推流
acLive.start({
url: this.settings.live_stream_server+this.stream_name // t1 就是流名称,可以理解为直播的房间号
},(ret, err)=>{
this.game.print(ret); // 状态如果为2则表示连接成功,其他都表示不成功
});
});
// 监听用户是否点击了返回键按钮,如果点击了,则关闭推流和摄像头信息采集功能
api.addEventListener({
name:'live_page_out'
},()=>{
acLive.close();
acLive.end();
}); }
}
})
}
</script>
</body>
</html>

live.html监听用户是否有返回的动作,如果监听到,则关闭摄像头采集功能和直播推流

day123:MoFang:直播间列表信息的前后端实现&创建房间的前后端实现的更多相关文章

  1. 疫情下的传统商企自救|4个Tips搭建销量过亿直播间

    新冠肺炎爆发以来,线下商企遭受巨大冲击.出于疫情防控需要,不少门店选择暂时停业:而消费者们更是响应号召.足不出户.这场疫情促使消费者的消费习惯和方式进一步转向线上订购转变,直播.短视频等领域逆势而起, ...

  2. 使用Selenium模拟浏览器抓取斗鱼直播间信息

    获取斗鱼直播间每个房间的名称.观看人数.tag.主播名字 代码: import time from multiprocessing import Pool from selenium import w ...

  3. 全栈开发——动手打造属于自己的直播间(Vue+SpringBoot+Nginx)

    前言 大学的学习时光临近尾声,感叹时光匆匆,三年一晃而过.同学们都忙着找工作,我也在这里抛一份简历吧,欢迎各位老板和猎手诚邀.我们进入正题.直播行业是当前火热的行业,谁都想从中分得一杯羹,直播养活了一 ...

  4. Websocket直播间聊天室教程 - GoEasy快速实现聊天室

    最近两年直播那个火啊,真的是无法形容!经常有朋友问起,我想实现一个直播间聊天或者我想开发一个聊天室, 要如何开始呢? 今天小编就手把手的教你用GoEasy做一个聊天室,当然也可以用于直播间内的互动.全 ...

  5. python - bilibili(一)获取直播间标题

    近几年,直播平台蛮火的.小时候,经过各种日漫的洗礼,在直播平台自然而然的就盯上了B站. 目前还是python菜鸟一枚,各位大佬请轻拍. 最终效果图: 闲话不说,我们来一步步解析B站的弹幕. 工具:py ...

  6. 基于python的直播间接口测试实战 详解结合项目

    基于python的直播间接口测试详解 一.基本用例内容描述 以设置白名单 /advisor/setUserWhiteList.do接口为例,该方法为POST at first,先要导入一些常用到的模块 ...

  7. 自己制作一个链表用来存储列表信息,并查找当前id信息,找上一条信息,下一条信息(信息浏览的时候方便使用)

    偶然看到某些网站在新闻详情中 ,往往是需要根据当前信息id获取到上一条信息和下一条信息的,而通常我们的做法是先获取当前信息,再获取上一条信息,再获取下一条信息,就需要发送三次查询才能够得到这些信息,一 ...

  8. 使用postMesssage()实现跨域iframe页面间的信息传递----转载

    由于web同源策略的限制,当页面使用跨域iframe链接时,主页面与子页面是无法交互的,这对页面间的信息传递造成了不小的麻烦,经过一系列的尝试,最后我发现有以下方法可以实现: 1. 子页面url传参 ...

  9. Extjs4.2如何实现鼠标点击统计图时弹出窗口来展示统计的具体列表信息

    var pageSize = 20;//初始化每页数据条数 var winTitle = '';//初始化窗口标题 /** *点击统计图时,弹出一个窗口,显示统计的详情列表信息, *该方法为项目中所有 ...

  10. Android 实现用户列表信息的功能,然后选择删除幻灯片删除功能

    在项目开发过程中.经常须要对用户列表的信息进行删除的操作.Android中经常使用的删除操作方式有两种 .一种就是类似微信的滑动出现删除button方式,另一种是通过CheckBox进行选择.然后通过 ...

随机推荐

  1. 【字符编码】字符编码 &amp;&amp; Base64编码算法

    一.前言 在前面的解决乱码的一文中,只找到了解决办法,但是没有为什么,说白了,就是对编码还是不是太熟悉,编码问题是一个很简单的问题,计算机从业人员应该也必须弄清楚,基于编码的应用有Base64加密算法 ...

  2. WCF 套接字连接已中止。这可能是由于处理消息时出错或远程主机超过接收超时或者潜在的网络资源问题导致的

    一个项目需要用到推送的功能,就是服务器主动推送数据给多台客户机.于是采用了WCF的双工通讯netTcpBinding 写好的项目,在本机测试都没有问题. 如果放在局域网内测试,问题出来了:先是安全性问 ...

  3. MongoDB学习笔记-04 索引

    索引是用来加速查询的.有了索引之后,数据库不必进行全表扫描,只需先在索引中查找,再根据找到的索引查找数据.MongoDB的索引几乎和传统关系型数据库一样. 创建索引 创建索引是在相应的集合中使用ens ...

  4. maven -- 学习笔记(四)实现在Eclipse用maven搭建springmvc项目(附构建步骤和详细实现代码)

    Learn from:http://www.cnblogs.com/fangjins/archive/2012/05/06/2485459.html,感谢楼主的分享,才有下面的这篇学习小结 一.环境准 ...

  5. HDU 1171 Big Event in HDU --暴力+生成函数

    题意:给n种房子,每种房子有一个值val和个数cnt,现在要把这些房子分成两部分,争取两部分总值相等,如果不能相等,让A>B,且A-B最小. 解法:先跑一次生成函数,c[n]表示组成总值为n的方 ...

  6. Java的平台无关性

    转载自:http://www.cnblogs.com/Y/archive/2011/03/22/JavaVM_Learning_Chapter2_Platform_Independence.html ...

  7. Android开发之创建桌面快捷方式

    Android创建桌面快捷方式就是在桌面这个应用上创建一个快捷方式,桌面应用:launcher2 通过查看launcher2的清单文件: <!-- Intent received used to ...

  8. nvm进行node多版本管理

    写在前面 nvm(nodejs version manager)是nodejs的管理工具,如果你需要快速更新node版本,并且不覆盖之前的版本:或者想要在不同的node版本之间进行切换: 使用nvm来 ...

  9. Problem : 1412 ( {A} + {B} )

    //集合中元素是不会重复的,所以完全没有必要将两个集合合并后再进行排序,交换排序的时间效率是O(n^2),将两个集合中的元素分别排序后输出即可.输出格式也非常需要 //注意的.输出一列元素赢以cout ...

  10. java 中使用正则表达式操作字符串

    import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.DataFl ...