技术峰会
BBS论坛(二)
2.1.cms后台登录界面完成(1)templates/cms/cms_login.html代码语言:javascript复制<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<meta name="description" content="">
<meta name="author" content="">
<title>CMS登录界面</title>
<!-- Bootstrap core CSS -->
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="{{ url_for('static',filename='cms/css/signin.css') }}" rel="stylesheet">
</head>
<body>
<div class="container">
<form class="form-signin">
<h2 class="form-signin-heading">请登录</h2>
<label for="inputEmail" class="sr-only">邮箱:</label>
<input type="email" id="inputEmail" class="form-control" placeholder="邮箱" required autofocus>
<label for="inputPassword" class="sr-only">密吗</label>
<input type="password" id="inputPassword" class="form-control" placeholder="密码" required>
<div class="checkbox">
<label>
<input type="checkbox" value="remember-me"> 记住我
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">立即登录</button>
</form>
</div> <!-- /container -->
</body>
</html>(2)static/cms/css/signin.css代码语言:javascript复制body {
padding-top: 40px;
padding-bottom: 40px;
background-color: #eee;
}
.form-signin {
max-width: 330px;
padding: 15px;
margin: 0 auto;
}
.form-signin .form-signin-heading,
.form-signin .checkbox {
margin-bottom: 10px;
}
.form-signin .checkbox {
font-weight: normal;
}
.form-signin .form-control {
position: relative;
height: auto;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
padding: 10px;
font-size: 16px;
}
.form-signin .form-control:focus {
z-index: 2;
}
.form-signin input[type="email"] {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}(3)cms/views.py代码语言:javascript复制# cmd/views.py
__author__ = 'derek'
from flask import Blueprint,views,render_template
bp = Blueprint("cms",__name__,url_prefix='/cms')
@bp.route('/')
def index():
return 'cms index'
class LoginView(views.MethodView):
def get(self):
return render_template('cms/cms_login.html')
def post(self):
pass
bp.add_url_rule('/login/',view_func=LoginView.as_view('login'))浏览器访问:http://127.0.0.1:5000/cms/login/2.2.cms后台登录功能完成(1)cms/cms_login.html代码语言:javascript复制 <form class="form-signin" method="post">
<h2 class="form-signin-heading">请登录</h2>
<label for="inputEmail" class="sr-only">邮箱:</label>
<input type="email" id="inputEmail" class="form-control" name="email" placeholder="邮箱" required autofocus>
<label for="inputPassword" class="sr-only">密吗</label>
<input type="password" id="inputPassword" class="form-control" name="password" placeholder="密码" required>
<div class="checkbox">
<label>
<input type="checkbox" value="1" name="remember"> 记住我
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">立即登录</button>
</form>
{% if message %}
<p style="text-align: center" class="text-danger">{{ message }}</p>
{% endif %}(2)cms/forms.py代码语言:javascript复制# cmd/forms.py
from wtforms import Form,StringField,IntegerField
from wtforms.validators import Email,InputRequired,Length
class LoginForm(Form):
email = StringField(validators=[Email(message='请输入正确的邮箱格式'),
InputRequired(message='请输入邮箱')])
password = StringField(validators=[Length(6,20,message='密码长度不够或超出')])
remember = IntegerField()(4)cms/views.py代码语言:javascript复制# cmd/views.py
__author__ = 'derek'
from flask import Blueprint,views,render_template,request,session
from flask import url_for,redirect
from .forms import LoginForm
from .models import CMSUser
bp = Blueprint("cms",__name__,url_prefix='/cms')
@bp.route('/')
def index():
return 'cms index'
class LoginView(views.MethodView):
def get(self,message=None):
return render_template('cms/cms_login.html',message=message)
def post(self):
form = LoginForm(request.form)
if form.validate():
email = form.email.data
password = form.password.data
remember = form.remember.data
user = CMSUser.query.filter_by(email=email).first()
if user and user.check_password(password):
session['user_id'] = user.id
if remember:
# 31天后过期
session.permanent = True
return redirect(url_for('cms.index'))
else:
return self.get(message='用户名或密码错误')
else:
#form.errors的错误信息格式,是一个字典,value是列表的形式
# {'email': ['请输入正确的邮箱格式'], 'password': ['密码长度不够或超出']}
message = form.errors.popitem()[1][0]
return self.get(message=message)
bp.add_url_rule('/login/',view_func=LoginView.as_view('login'))(4)config.py代码语言:javascript复制import os
SECRET_KEY = os.urandom(24)2.3.cms后台登录限制(1)config.py代码语言:javascript复制CMS_USER_ID = 'abcdefg' #随便写一值,这样session更加安全(2)修改LoginView代码语言:javascript复制session[config.CMS_USER_ID] = user.id(3)cms/decorators.py代码语言:javascript复制# cms/decorators.py
from flask import session,redirect,url_for
from functools import wraps
import config
def login_required(func):
@wraps(func)
def inner(*args,**kwargs):
if config.CMS_USER_ID in session:
return func(*args,**kwargs)
else:
return redirect(url_for('cms.login'))
return inner(4)cms/cms_login.py代码语言:javascript复制@bp.route('/')
@login_required
def index():
return 'cms index'2.4.cms后台模板渲染完成(1)static/cms/css/base.css代码语言:javascript复制/*
* Base structure
*/
/* Move down content because we have a fixed navbar that is 50px tall */
body {
padding-top: 50px;
overflow: hidden;
}
/*
* Global add-ons
*/
.sub-header {
padding-bottom: 10px;
border-bottom: 1px solid #eee;
}
/*
* Top navigation
* Hide default border to remove 1px line.
*/
.navbar-fixed-top {
border: 0;
}
/*
* Sidebar
*/
/* Hide for mobile, show later */
.sidebar {
display: none;
}
@media (min-width: 768px) {
.sidebar {
position: fixed;
top: 51px;
bottom: 0;
left: 0;
z-index: 1000;
display: block;
padding: 20px;
overflow-x: hidden;
overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
background-color: #363a47;
border-right: 1px solid #eee;
margin-top: -1px;
}
}
.nav-sidebar{
padding: 5px 0;
margin-left: -20px;
margin-right: -20px;
}
.nav-sidebar > li{
background: #494f60;
border-bottom: 1px solid #363a47;
border-top: 1px solid #666;
line-height: 35px;
}
.nav-sidebar > li > a {
background: #494f60;
color: #9b9fb1;
margin-left: 25px;
display: block;
}
.nav-sidebar > li a span{
float: right;
width: 10px;
height:10px;
border-style: solid;
border-color: #9b9fb1 #9b9fb1 transparent transparent;
border-width: 1px;
transform: rotate(45deg);
position: relative;
top: 10px;
margin-right: 10px;
}
.nav-sidebar > li > a:hover{
color: #fff;
background: #494f60;
text-decoration: none;
}
.nav-sidebar > li > .subnav{
display: none;
}
.nav-sidebar > li.unfold{
background: #494f60;
}
.nav-sidebar > li.unfold > .subnav{
display: block;
}
.nav-sidebar > li.unfold > a{
color: #db4055;
}
.nav-sidebar > li.unfold > a span{
transform: rotate(135deg);
top: 5px;
border-color: #db4055 #db4055 transparent transparent;
}
.subnav{
padding-left: 10px;
padding-right: 10px;
background: #363a47;
overflow: hidden;
}
.subnav li{
overflow: hidden;
margin-top: 10px;
line-height: 25px;
height: 25px;
}
.subnav li.active{
background: #db4055;
}
.subnav li a{
/*display: block;*/
color: #9b9fb1;
padding-left: 30px;
height:25px;
line-height: 25px;
}
.subnav li a:hover{
color: #fff;
}
.nav-group{
margin-top: 10px;
}
.main {
padding: 20px;
}
@media (min-width: 768px) {
.main {
padding-right: 40px;
padding-left: 40px;
}
}
.main .page-header {
margin-top: 0;
}
/*
* Placeholder dashboard ideas
*/
.placeholders {
margin-bottom: 30px;
text-align: center;
}
.placeholders h4 {
margin-bottom: 0;
}
.placeholder {
margin-bottom: 20px;
}
.placeholder img {
display: inline-block;
border-radius: 50%;
}
.main_content{
margin-top: 20px;
}
.top-group{
padding: 5px 10px;
border-radius: 2px;
background: #ecedf0;
overflow: hidden;
}
.top-box{
overflow: hidden;
background: #ecedf0;
padding: 10px 5px;
}(2)static/cms/js/base.js代码语言:javascript复制/**
* Created by Administrator on 2018/6/2.
*/
/**
* Created by Administrator on 2016/12/17.
*/
$(function () {
$('.nav-sidebar>li>a').click(function (event) {
var that = $(this);
if(that.children('a').attr('href') == '#'){
event.preventDefault();
}
if(that.parent().hasClass('unfold')){
that.parent().removeClass('unfold');
}else{
that.parent().addClass('unfold').siblings().removeClass('unfold');
}
console.log('coming....');
});
$('.nav-sidebar a').mouseleave(function () {
$(this).css('text-decoration','none');
});
});
$(function () {
var url = window.location.href;
if(url.indexOf('profile') >= 0){
var profileLi = $('.profile-li');
profileLi.addClass('unfold').siblings().removeClass('unfold');
profileLi.children('.subnav').children().eq(0).addClass('active').siblings().removeClass('active');
} else if(url.indexOf('resetpwd') >= 0){
var profileLi = $('.profile-li');
profileLi.addClass('unfold').siblings().removeClass('unfold');
profileLi.children('.subnav').children().eq(1).addClass('active').siblings().removeClass('active');
} else if(url.indexOf('resetemail') >= 0){
var profileLi = $('.profile-li');
profileLi.addClass('unfold').siblings().removeClass('unfold');
profileLi.children('.subnav').children().eq(2).addClass('active').siblings().removeClass('active');
} else if(url.indexOf('posts') >= 0){
var postManageLi = $('.post-manage');
console.log(postManageLi);
postManageLi.addClass('unfold').siblings().removeClass('unfold');
}else if(url.indexOf('boards') >= 0){
var boardManageLi = $('.board-manage');
boardManageLi.addClass('unfold').siblings().removeClass('unfold');
}else if(url.indexOf('permissions') >= 0){
var permissionManageLi = $('.permission-manage');
permissionManageLi.addClass('unfold').siblings().removeClass('unfold');
}else if(url.indexOf('fusers') >= 0){
var userManageLi = $('.user-manage');
userManageLi.addClass('unfold').siblings().removeClass('unfold');
}else if(url.indexOf('cusers') >= 0){
var cmsuserManageLi = $('.cmsuser-manage');
cmsuserManageLi.addClass('unfold').siblings().removeClass('unfold');
}else if(url.indexOf('croles') >= 0){
var cmsroleManageLi = $('.cmsrole-manage');
cmsroleManageLi.addClass('unfold').siblings().removeClass('unfold');
}else if(url.indexOf('comments') >= 0) {
var commentsManageLi = $('.comments-manage');
commentsManageLi.addClass('unfold').siblings().removeClass('unfold');
}else if(url.indexOf('banners')>=0){
var bannerManageLi=$('.banner-manage');
bannerManageLi.addClass('unfold').siblings().removeClass('unfold');
}
});(3)templates/common/_macros.html创建一个宏代码语言:javascript复制{#“-”表示去掉换行#}
{% macro static(filename) -%}
{{ url_for("static",filename=filename) }}
{%- endmacro %}(4)templates/cms/cms_index.html代码语言:javascript复制{% from "common/_macros.html" import static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>标题</title>
<script src="http://cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
<link href="http://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="http://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="{{ static('cms/css/base.css') }}">
<script src="{{ static('cms/js/base.js')}}"></script>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Zhang_derek论坛管理后台</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li><a href="#">derek<span>[超级管理员]</span></a></li>
<li><a href="#">注销</a></li>
</ul>
<form class="navbar-form navbar-right">
<input type="text" class="form-control" placeholder="查找...">
</form>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
<ul class="nav-sidebar">
<li class="unfold"><a href="#">首页</a></li>
<li class="profile-li">
<a href="#">个人中心<span></span></a>
<ul class="subnav">
<li><a href="#">个人信息</a></li>
<li><a href="#">修改密码</a></li>
<li><a href="#">修改邮箱</a></li>
</ul>
</li>
<li class="nav-group post-manage"><a href="#">帖子管理</a></li>
<li class="comments-manage"><a href="#">评论管理</a></li>
<li class="board-manage"><a href="#">板块管理</a></li>
<li class="nav-group user-manage"><a href="#">用户管理</a></li>
<li class="nav-group cmsuser-manage"><a href="#">CMS用户管理</a></li>
<li class="cmsrole-manage"><a href="#">CMS组管理</a></li>
</ul>
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<h1>我的论坛</h1>
</div>
</div>
</div>
</body>
</html>(5)app/cms/views.py代码语言:javascript复制@bp.route('/')
@login_required
def index():
return render_template('cms/cms_index.html')访问:http://127.0.0.1:5000/cms/
web安全论坛
1.web应用程序所采用的防卫机制的几个核心构成:1、处理用户对应用程序的数据和功能的访问,以防止用户未经授权访问。2、处理用户的输入,以防止恶意的输入导致未预期的行为。3、处理攻击,以确保应用程序在 1.web应用程序所采用的防卫机制的几个核心构成:1、处理用户对应用程序的数据和功能的访问,以防止用户未经授权访问。
2、处理用户的输入,以防止恶意的输入导致未预期的行为。
3、处理攻击,以确保应用程序在被直接攻击时作出恰当的行为,如采取适当的防御和进攻性措施,以挫败攻击。
4、通过使管理员能够监控应用程序的活动和配置应用程序的功能来管理应用程序本身。1.1处理用户访问大多数web应用程序都使用下面的三重相关的安全机制来处理访问:
1、验证
2、会话管理
3、访问控制1.1.1验证验证机制在一个应用程序的用户访问处理中是一个最基本的部分。验证就是确
定该用户的有效性。大多数的web应用程序都采用常规的验证模型,即用户提
交一个用户名和密码,应用程序检查它的有效性。在安全性很重要的应用程序
中,如在线银行,这个基本的验证模型常增加额外的证书和多级登录过程。在
安全性要求更高的时候,其它的一些验证模型可以被用,如客户端证书,智能
卡或挑战/应答(challenge-response)tokens。challenge-responsetokens的过程:
用户要求登录时,系统产生一个随机数字串发送给用户。用户将这个串输入到
token设备中,token设备将这个串与用户的秘密口令按特定的算法进行运算并
产生一个回应串发送给系统,系统用同样的算法做验算即可验证用户身份。除了核心的登录过程外,验证机制也常采用其它的一些辅助功能,如自注册
(self-registration,比如注册后通过邮件中的链接激活帐户),帐户恢复以及
密码更改功能。尽管验证机制表面上简单,但是验证机制在设计和实现方面却
存在着广泛的缺陷。一般的问题可能使一个攻击者能够识别其他用户的用户名
,猜测他们的密码或者通过利用验证的逻辑缺陷绕过这个登录函数。当你攻击
一个web应用程序时,你应该花大量的注意力在该web应用程序所包含的各种
验证相关的功能方面。验证方面的缺陷将使你能够未经授权地访问敏感数据和
功能。1.1.2会话管理处理用户访问的下一个工作是管理授权用户的会话。在成功登录到应用程序后,用户将从他们的浏览发送一系列的HTTP请求来访问一些页面和功能。同时,该应用程序将接收无数来自不同用户的其它的请求,有授权的用户,也有匿名的用户。为了实施有效的访问控制,应用程序需要一个方法来识别和处理这一系列来自每个不同用户的请求。实际上大多数的web应用程序都通过为每个用户创建一个会话和发送给用户一个令牌(token)来识别会话。会话本身是位于服务上的一套数据结构,它被用来跟踪与应用程序交互的用户的状态。令牌是一个具有唯一性的字符串,应用程序将它映射到会话。当一个用户已经收到一个令牌时,浏览器在随后的每次HTTP请求中会自动将这个令牌提交给服务器,以使得应用程序能够将该请求与用户相关联起来。尽管许多应用程序使用隐藏的表单域或URL查询字符串来实现这一目的,但是HTTPcookies是传送会话令牌的标准方法。如果一个用户在指定的时间内没有产生一个请求,那么会话将被认为结束。对于之后的访问,web应用程序会要求你重新登录。就攻击而言,会话管理机制高度地依赖于它的令牌的安全性。针对会话管理机制的多数攻击都是试图损害发送给别的用户的令牌。有可能的话,一个攻击者可以伪装成受害的授权用户来使用web应用程序。这一漏洞主要来自于两方面,其一是令牌生成的方法的缺陷,使得攻击者能够猜测到发送给别的用户的令牌,其二是令牌的后续处理的方法的缺陷,使得攻击者能够捕获别的用户的令牌。有少部分的应用程序通过另外的识别方式省掉了会话令牌的需要,比如,如果一个HTTP的内建的授权机制被使用的话,那么浏览器对于每次的请求都自动重新提交用户的证书,使得应用程序能够直接从证书识别用户。也存在其它别的方法,应用程序存储状态信息在客户端而非服务器上,这些状态信息通常采用加密的形式以防止被篡改。1.1.3访问控制处理用户访问的最后一步是正确决定对于每个独立的请求是允许还是拒绝。如果前面的机制都工作正常,那么应用程序就知道每个被接受到的请求所来自的用户的id。它据此决定用户对所请求要执行的动作或要访问的数据是否得到了授权。
访问控制机制通常需要根据对应用程序的不同部分或不同类型的功能的考虑,实现一些小而好的逻辑。一个应用程序可能支持许多不同的用户角色,每个都牵涉到特定权限的不同组合。个别的用户可能会被允许访问该应用程序所容纳的整个数据的一个子集。特定的函数能够实现事务限制和其它的检查,所有这些都需要基于用户的id来得到正确的实施。
由于访问控制本身的复杂性,这使得它成为使得一个攻击者能够获得未授权访问数据和功能这一安全漏洞的常见根源。开发者经常对用户会如何与应用程序交互作出有缺陷的假设,以及经常由于省略了对某些应用程序功能的访问控制检查而造成疏忽。由于对于每项功能都需要重复相同的检查,所以探查这些漏洞通常是十分费力的。然而由于访问控制缺陷的普遍性,当你攻击一个web应用程序时这种努力是值得的。1.2处理用户的输入
很多针对web应用程序的攻击都涉及到提交未预期的输入,它导致了该应用程序设计者没有料到的行为。因此,对于应用程序安全性防护的一个关键的要求是它必须以一个安全的方式处理用户的输入。基于输入的漏洞可能出现在一个应用程序的功能的任何地方,并与每上通常使用的技术类型相关。对于这种攻击,输入验证是常用的必要防护。不存在通用的单一的防护机制。
1.2.1各种类型的输入
一个典型的web应用程序在不同范围形式内处理用户提供的数据。某种类型的输入验证可能对于所有这些输入形式是不可行的。
在许多情况下,一个应用程序对于特定的输入项能够实施非常严格的验证检查。比如提交给登录函数的用户名可以要求最大长度和只能包含字母。
在另外一些情况下,应用程序必须容纳更大范围的可能性的输入。比如提交给一个个人信息页面的地址字段,它可以包含字母、数字、空格、连接符,撇号以及其它字符。对于这种类型,仍然需要加以可行限制,如不能超过合适的长度,以及不能包含HTML标记。
在某些情形下,一个应用程序可能需要接受来自用户的任意的输入。比如,一个blog应用程序的用户,他创建的博客的主题的web应用程序攻击,那么他提交的内容则可以包含明显的所要讨论的攻击字符串。该应用程序需要以一个安全的方法把这些输入存储在一个数据库中并写到磁盘上,以及回显给用户。所以该应用程序就不能因为输入看起来有潜在的恶意简单拒绝。
除了来自用户的浏览器的各种输入外,典型的应用程序也接受从服务器到客户端,然后回传给服务器的数据。这些项目包括诸如cookies和隐藏的表单字段这些,它们不会被这个应用程序的普通用户所看到,但是对于攻击者来说是可见和可修改的。在这些情况中,应用程序可以对所接收的数据进行特定的验证。例如要求参数必须有一个指定数值集中的值,如表明用户所偏爱的语言的cookie,或以一个指定的格式,如一个客户的ID号。进一步说,当应用程序发现返回自用户的由服务器生成的数据已经被修改了的话,这通常就表明该用户正在探测应用程序的漏洞。在此类情况下,应用程序应该拒绝请求并记录下这个探测事件。1.2.2处理输入的方式
处理用户的输入有很多方式.不同的方式适合不同的情形和不同的输入类型,有些时候一个组合的方式是可取的.
1.2.2.1黑名单
这种方式通常使用一个黑名单,它包含已知的被用在攻击方面的一套字面上的字符串或模式.验证机制阻挡任何匹配黑名单的数据.
一般来说,这种方式是被认为对于检查用户的输入效果最差的一种方式.主要有两个原因,首先是,web应用程序中的一个典型的漏洞可以使用很多种不同的输入来被利用,输入可以是被加密的或以各种不同的方法表示.其二,漏洞利用的技术是在不断地改进的.有关利用已存在的漏洞类型的新的方法不可能被当前黑名单阻挡.
1.2.2.2白名单
这种方式采用一个白名单,它包含一套字面上的字符串或模式,或一套标准,它们用来匹配符合要求的输入.这种检查机制允许匹配白名单的数据,阻止之外的任何数据.这种方式虽然最有效,但不是通用的,比如撇号和连字符可以被用于对数据库的攻击,但是有时应用程序却应该允许它的输入.
1.2.2.3过滤
这种方式下,潜在的恶意字符被删除,留下安全的字符,或者在进一步处理被执行之前,它们被适当地加密或去掉.
基于数据过滤的方式通常是十分有效的,并且在许多情形中,可作为处理恶意输入的通用解决方案.比如,针对跨站脚本攻击的通常的防护是在字符被嵌入到应用程序的页面之前进行HTML加密.然而如果几种潜在的恶意数据在一个输入项中话,有效的过滤是困难的.在这种情况下,边界检查方法则是更适用的.
1.2.2.4安全地处理数据
非常多的web应用程序漏洞的出现是因为用户提供的数据是以不安全的方法被处理的.在一些情况下,存在安全的编程方法能够避免通常的问题.例如,SQL注入攻击能够通过正确的参数查询被阻止.在另外的情况中,应用程序功能设计的方法存在内在的不安全性,比如把用户的输入传递给操作系统的命令解释器.
安全处理数据的方式不能适用于web应用程序需要执行的每种工作,但是它对于处理潜在的恶意输入是通常有效的方式.
1.2.2.5语义检查
语义检查用于防止各种变形数据的输入,这些数据的内容被精心制作来干扰应用程序的处理。然而对于有一些漏洞,攻击者的输入在表面看来和普通用户的输入是一样的,说到底检查就失去了作用。例如一个攻击者可能会通过改变隐藏的表意字段中的帐号来试图获得对他人银行帐户的访问。要阻止这种未授权的访问,应用程序需要验证帐号是否属于该用户。
1.2.2.5边界检查
对于web应用程序,核心安全问题的出现是因为接受自用户的数据是不可信任的.尽管在客户端实现的输入验证检查能够能够提高性能和用户体验,但是这对于实际到达服务器的数据却没有任何担保.用户的数据在被服务端应用程序第一时间接受到的一刻就是边界,此时应用程序需要采取步骤来防卫恶意的输入.
鉴于核心问题的本质,对于互联网边界间的输入检查这一问题的思考是很有意义的.哪些是"恶意的"或不可信任的,以及服务端应用程序哪些是"好的"或可信任的.我们给出一个简单的想法:输入验证的角色是清除到达的数据中的潜在的恶意数据,然后把干净的数据传递给可信任的应用程序.据此,这些数据可以被信任和处理而不做进一步的检查或考虑可能的攻击.
当我们开始检查一些实际的漏洞的时候,会很明显地发现上面的简单的想法是不充分的.原因如下:(1).鉴于web应用程序实现的功能的广泛性,以及所应用的技术的不同,一个典型的web应用程序需要防卫大量的不同的基于输入的攻击.每种输入攻击都可能采用了一套不同的数据.针对外部边界仅设计单一的一个机制来防卫所有这些攻击是非常困难的.(2).许多应用程序的函数包含相互牵连的一系列不同的处理,单个用户所提交的一块数据可能导致不同组件之间的许多操作,上一个的输出可能作为下一个的输入.当数据被传送时,它可能有所变化,与最初的输入可能有所不同,这样一个熟练的黑客可能能够操纵这个应用程序以在处理的关键阶段导致恶意输入的产生,也就是攻击接受该数据的组件.这对于在外部边界预见用户输入的每块数据的处理的所有结果来实现一个验证机制是十分困难的.(3).防卫不同种类的输入攻击可能需要对用户的输入执行不同的验证检查,这些验证检查是不兼容的。例如阻止跨站脚本攻击可以要求HTML加密“>”为"gt";而阻止命令注入攻击(commandinject)可能需要阻止包含&和;字符的输入。试图在应用程序的外部边界同时阻止所有种类的攻击有时是不可能的。一个使用边界检查概念的更有效的模型是,服务器端的每个组件或功能单元把它的输入当作是来自一个潜在的恶意源。数据检查除了在客户端和服务端之间的边界外,也在这些认为可信的边界被执行。这个模型对前面列出的问题列表提供了一个解决方案。每个组件针对自身可能的漏洞的特定的输入攻击能够自我防卫。当数据在不同的组件间传递时,验证检查就可以对前面传来数据进行检查,由于不同有验证检查是在不同的处理阶段被执行的,所以他们之间不会产生冲突。下图演示了一个防卫恶意输入最有效的方式,用户登录致使对用户提交的输入进行了几步处理,并且每步上都执行了适当的检查。
(1).应用程序接受用户的登录的详细数据.表单处理检查输入的每一项,包括允许的字符、长度是否在指定的范围内、以及不能包含任何已知的攻击特征码.
(2).应用程序执行一个SQL查询来验证用户的证书.为了阻止SQL注入攻击,用户输入的任何可能攻击数据库的字符在构造查询之前都被去掉.
(3).如果登录成功,应用程序将把来自用户的数据传递给一个SOAP服务器以检索他的帐户的更多的信息.为了阻止SOAP注入攻击,用户数据中的任何XML元字符都被适当地加密处理.
(4).应用程序把用户的账户信息回传给用户的浏览器以显示.为了防止跨站脚本攻击,应用程序HTML加密嵌在返回的页面中的用户提供的任何数据.总之,所有牵涉的组件间都应作边界检查.情况的变化会导致所涉及的组件发生变化.例如如果登录失败后,应用程序会发送一个警告邮件给该用户的话,那么任何合并到该邮件中的用户数据可能需要针对SMTP注入攻击作检查.1.2.2.6多步检查和恢复如果对用户的输入没有进行仔细的多级检查的话,攻击者构建的输入就可能会得逞。当一个应用程序试图通过删除或加密特定的字符或表达式来过滤用户的输入的话,这种情况就可能会出现。例如,一个应用程序可能试图从用户提交的数据中通过去掉表达式<script>来防止某些跨站脚本攻击,那么攻击者可能通过输入<scr<script>ipt>来绕过这个过滤。这是因为这个过滤没有被递归地使用,当<scr<script>ipt>中间的<script>被去掉后,剩下的还是<script>。类似的情况就是,攻击者可以利用多步检查的顺序来绕过这个过滤。例如如果一个应用程序第一是递归地去掉<script>表达式,然后是去掉"符号的话,那么<scr"ipt>就可以成功绕过这个过滤。另一个问题是在用户输入的数据被解密时会发生的。从用户浏览器过来的数据会是以不同方法加密了的数据,那么就需要对这些数据进行恢复,也就是转换或解密为通常的字符。如果解密是在输入过滤之后,那么攻击者就可以通过加密来绕过这个检查机制。例如,如果一个应用程序通过删除用户输入数据中"号来防止某些SQL注入攻击的话,由于过滤先于恢复,那么攻击者可以使用"号的URL加密形式%27来绕过这个检查机制。同理,如果检查机制也会去掉%27话,只要没有递归处理,那么%%2727就能够得逞。有时候避免多步检查和恢复中存在的问题是比较困难的。不存在单一的方案能够解决这些问题。有些情况下,递归地处理一个有问题的字符可能会导致死循环,通常,这只能在所执行的检查类型上来根据情况处理,情况允许的话,更好的方法就是简单地拒绝某些类型的恶意输入。今天文章到此就结束了,感谢您的阅读。
BBS论坛(十)
10.1.客户端权限验证功能完成(1)cms/cms_profile显示当前用户的角色和权限代码语言:javascript复制 <tr>
<td>角色:</td>
<td>
{% for role in user.roles %}
{{ role.name }}
{% if not loop.last %},{% endif %}
{% endfor %}
</td>
</tr>
<tr>
<td>权限:</td>
<td>
{% for role in user.roles %}
{{ role.desc }}
{% if not loop.last %}/{% endif %}
{% endfor %}
</td>
</tr>(2)cms/hooks.py代码语言:javascript复制@bp.context_processor
def cms_context_pocessor():
return {'CMSPermission':CMSPermission}(3)cms/cms_base.html不同的角色,显示不同的内容代码语言:javascript复制{% set cms_user = g.cms_user %}
{% if cms_user.has_permission(CMSPermission.POSTER) %}
<li class="nav-group post-manage"><a href="#">帖子管理</a></li>
{% endif %}
{% if cms_user.has_permission(CMSPermission.COMMENTER) %}
<li class="comments-manage"><a href="#">评论管理</a></li>
{% endif %}
{% if cms_user.has_permission(CMSPermission.BOARDER) %}
<li class="board-manage"><a href="#">板块管理</a></li>
{% endif %}
{% if cms_user.has_permission(CMSPermission.FRONTUSER) %}
<li class="nav-group user-manage"><a href="#">前台用户管理</a></li>
{% endif %}
{% if cms_user.has_permission(CMSPermission.CMSUSER) %}
<li class="nav-group cmsuser-manage"><a href="#">CMS用户管理</a></li>
{% endif %}
{% if cms_user.is_developer %}
<li class="cmsrole-manage"><a href="#">CMS组管理</a></li>
{% endif %}(4)添加用户和角色代码语言:javascript复制#添加访问者
python manage.py create_cms_user -u 我是访问者 -p 123456 -e [email protected]
python manage.py add_user_to_role -e [email protected] -n 访问者
#添加运营者
python manage.py create_cms_user -u 我是运营者 -p 123456 -e [email protected]
python manage.py add_user_to_role -e [email protected] -n 运营
#添加管理员
python manage.py create_cms_user -u 我是管理员 -p 123456 -e [email protected]
python manage.py add_user_to_role -e [email protected] -n 管理员不同的用户登录到后台cms显示不同的内容 开发者访问者10.2.服务端权限验证功能完成(1)后台剩余的html页面cms_posts.html代码语言:javascript复制{% extends 'cms/cms_base.html' %}
{% block title %}
帖子管理
{% endblock %}
{% block head %}
{% endblock %}
{% block page_title %}
{{ self.title() }}
{% endblock %}
{% block main_content %}
帖子管理页面
{% endblock %}其它几个一样代码语言:javascript复制cms_comments.html
cms_boards.html
cms_fusers.html
cms_cusers.html
cms_croles.html(2)cms/decorators.py添加一个权限验证的装饰器代码语言:javascript复制def permission_required(permission):
def outter(func):
@wraps(func)
def inner(*args,**kwargs):
user = g.cms_user
if user.has_permission(permission):
return func(*args,**kwargs)
else:
return redirect(url_for('cms.index'))
return inner
return outter(3)cms/views.py代码语言:javascript复制@bp.route('/posts/')
@login_required
@permission_required(CMSPermission.POSTER)
def posts():
return render_template('cms/cms_posts.html')
@bp.route('/comments/')
@login_required
@permission_required(CMSPermission.COMMENTER)
def comments():
return render_template('cms/cms_comments.html')
@bp.route('/boards/')
@login_required
@permission_required(CMSPermission.BOARDER)
def boards():
return render_template('cms/cms_boards.html')
@bp.route('/fusers/')
@login_required
@permission_required(CMSPermission.FRONTUSER)
def fusers():
return render_template('cms/cms_fusers.html')
@bp.route('/cusers/')
@login_required
@permission_required(CMSPermission.CMSUSER)
def cusers():
return render_template('cms/cms_cusers.html')
@bp.route('/croles/')
@login_required
@permission_required(CMSPermission.ALL_PERMISSION)
def croles():
return render_template('cms/cms_croles.html')(4)cms/cms_base.html修改url链接代码语言:javascript复制 {% set cms_user = g.cms_user %}
{% if cms_user.has_permission(CMSPermission.POSTER) %}
<li class="nav-group post-manage"><a href="{{ url_for('cms.posts') }}">帖子管理</a></li>
{% endif %}
{% if cms_user.has_permission(CMSPermission.COMMENTER) %}
<li class="comments-manage"><a href="{{ url_for('cms.comments') }}">评论管理</a></li>
{% endif %}
{% if cms_user.has_permission(CMSPermission.BOARDER) %}
<li class="board-manage"><a href="{{ url_for('cms.boards') }}">板块管理</a></li>
{% endif %}
{% if cms_user.has_permission(CMSPermission.FRONTUSER) %}
<li class="nav-group user-manage"><a href="{{ url_for('cms.fusers') }}">前台用户管理</a></li>
{% endif %}
{% if cms_user.has_permission(CMSPermission.CMSUSER) %}
<li class="nav-group cmsuser-manage"><a href="{{ url_for('cms.cusers') }}">CMS用户管理</a></li>
{% endif %}
{% if cms_user.is_developer %}
<li class="cmsrole-manage"><a href="{{ url_for('cms.croles') }}">CMS组管理</a></li>
{% endif %}
BBS论坛(十九)
19.1.cms轮播图管理页面布局(1)cms/cms_base.html代码语言:javascript复制<li class="nav-group banner-manage"><a href="{{ url_for('cms.banners') }}">轮播图管理</a></li>(2)views.y代码语言:javascript复制@bp.route('/banners/')
@login_required
def banners():
return render_template('cms/cms_banners.html')(3)cms/banners.html代码语言:javascript复制{% extends 'cms/cms_base.html' %}
{% block title %}
轮播图管理
{% endblock %}
{% block head %}
<style>
.top-box{
overflow: hidden;
background: #ecedf0;
padding: 10px 5px;
}
.top-box button{
float: right;
}
</style>
{% endblock %}
{% block page_title %}
{{ self.title() }}
{% endblock %}
{% block main_content %}
<div class="top-box">
<button class="btn btn-warning">添加轮播图</button>
</div>
<table class="table table-bordered">
<thead>
<tr>
<td>名称</td>
<td>图片链接</td>
<td>优先级</td>
<td>跳转链接</td>
<td>创建日期</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr>
</tr>
</tbody>
</table>
{% endblock %}19.2.添加轮播图模态对话框的制作cms_banners.html代码语言:javascript复制{% block main_content %}
<div class="top-box">
<button class="btn btn-warning" data-toggle="modal" data-target="#banner-dialog">添加轮播图</button>
</div>
<!-- Modal -->
<div class="modal fade" id="banner-dialog" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">times;</span></button>
<h4 class="modal-title" id="myModalLabel">轮播图</h4>
</div>
<div class="modal-body">
<form action="" class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label">名称</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="name" placeholder="轮播图名称">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">图片</label>
<div class="col-sm-7">
<input type="text" class="form-control" name="img_url" placeholder="轮播图图片">
</div>
<button class="col-sm-2 btn btn-info">添加图片</button>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">跳转</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="link_url" placeholder="跳转链接">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">权重</label>
<div class="col-sm-10">
<input type="number" class="form-control" name="priority" placeholder="权重">
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary">保存</button>
</div>
</div>
</div>
</div>
{% endblock %}代码语言:javascript复制{% extends 'cms/cms_base.html' %}
{% block title %}
轮播图管理
{% endblock %}
{% block head %}
<style>
.top-box {
overflow: hidden;
background: #ecedf0;
padding: 10px 5px;
}
.top-box button {
float: right;
}
</style>
{% endblock %}
{% block page_title %}
{{ self.title() }}
{% endblock %}
{% block main_content %}
<div class="top-box">
<button class="btn btn-warning" data-toggle="modal" data-target="#banner-dialog">添加轮播图</button>
</div>
<table class="table table-bordered">
<thead>
<tr>
<td>名称</td>
<td>图片链接</td>
<td>优先级</td>
<td>跳转链接</td>
<td>创建日期</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr>
</tr>
</tbody>
</table>
<!-- Modal -->
<div class="modal fade" id="banner-dialog" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">times;</span></button>
<h4 class="modal-title" id="myModalLabel">轮播图</h4>
</div>
<div class="modal-body">
<form action="" class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label">名称</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="name" placeholder="轮播图名称">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">图片</label>
<div class="col-sm-7">
<input type="text" class="form-control" name="img_url" placeholder="轮播图图片">
</div>
<button class="col-sm-2 btn btn-info">添加图片</button>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">跳转</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="link_url" placeholder="跳转链接">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">权重</label>
<div class="col-sm-10">
<input type="number" class="form-control" name="priority" placeholder="权重">
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary">保存</button>
</div>
</div>
</div>
</div>
{% endblock %}
BBS论坛(七)
7.1.修改邮箱界面完成(1)cms/cms_resetemail.html代码语言:javascript复制{% extends 'cms/cms_base.html' %}
{% block title -%}
修改邮箱
{%- endblock %}
{% block head %}
{% endblock %}
{% block page_title -%}
{{ self.title() }}
{%- endblock %}
{% block main_content %}
<form action="" method="post">
<div class="form-container">
<div class="form-group">
<div class="input-group">
<input type="email" name="email" placeholder="新邮箱" class="form-control">
<span class="input-group-addon">获取验证码</span>
</div>
</div>
<div class="form-group">
<div class="input-group">
<input type="text" name="captcha" placeholder="邮箱验证码" class="form-control">
</div>
</div>
<div class="form-group">
<button class="btn btn-primary" id="submit">立即修改</button>
</div>
</div>
</form>
{% endblock %}(2)cms.views.py代码语言:javascript复制class ResetEmail(views.MethodView):
def get(self):
return render_template('cms/cms_resetemail.html')
def post(self):
pass
bp.add_url_rule('/resetemail/',view_func=ResetEmail.as_view('resetemail'))(3)cms/cms_base.html代码语言:javascript复制<li><a href="{{ url_for('cms.resetemail') }}">修改邮箱</a></li>(3)static/cms/css/base.css把cms_resetpwd.html中下面的样式放到base.css里面去,这样cms_resetemail和cms_resetpwd都可以用代码语言:javascript复制.form-container{
width: 300px;
}修改邮箱界面:7.2.Flask-mail的使用以及邮箱的配置(1)exts.py代码语言:javascript复制from flask_mail import Mail
mail = Mail()(2)Perfect_bbs.py代码语言:javascript复制from exts import db,mail
mail.init_app(app)(3)config.py代码语言:javascript复制MAIL_SERVER = "SMTP.qq.com"
MAIL_PORT = "587"
MAIL_USE_TLS = True
# MAIL_USE_SSL
MAIL_USERNAME = "[email protected]"
MAIL_PASSWORD = "zusbbabvfbdyqihxag"
MAIL_DEFAULT_SENDER = "[email protected]"(4)cms/views.py代码语言:javascript复制@bp.route('/email/')
def send_email():
#1.标题,2.收件人,3.发送的正文内容
message = Message(subject='derek论坛密码修改邮件发送',recipients=['[email protected]',],body='第一次测试发送邮件')
mail.send(message) #发送邮件
return '邮件发送成功'测试功能,访问地址就会发送邮件:http://127.0.0.1:5000/cms/email/
QQ、微博、陌陌:社交难逃社交命
1994年,大陆第一个互联网BBS——曙光站上线。之后,水木清华、猫扑、西祠胡同等BBS网站接连出现,国内社交媒体正式进入成长期。1999年,被腾讯人称为“饿死鬼小精灵”的OICQ诞生。腾讯QQ在即时通讯领域一骑绝尘,成为社交王者。2002年Blog传入中国,以此为原型的博客中国成立。随着“木子美”事件的助推,各大网站都在进军博客,新浪、网易等门户网站相继开火,门户博客全面爆发。2005年,校内网上线;2008年,开心网上线,5Q网、底片网等SNS网站陆续推出,SNS网站呈现出强劲生命力。2007年,被誉为“中国最早的微博”的饭否网上线,但饭否网两年后被关停。2009年,新浪微博悄然上线,正式进入微博时代。2011年,微信上线。此后,微信势如破竹,一步步攻入其他玩家的腹地,一举成为社交霸主。同年,陌陌踏入陌生人社交赛道,引起巨大反响。此后,小红书、抖音等互联网产品接连问世,也都不约而同地踏入社交领域。社交赛道硝烟滚滚,不断有新的社交产品进入市场,试图讲出新故事。时至今日,虽然QQ、微博、陌陌、微信等社交产品依旧活跃在应用榜上,但也有无数社交产品成为时代的眼泪,更有甚者都来不及被广大用户群知晓,就已经没了身影。从大红大紫到老态龙钟社交是人类社会永恒的需求,但没有哪类产品能够永垂不朽。纵使是QQ、微博、陌陌这些资深玩家也难免会力不从心,毕竟这条赛道永远都不缺讲故事的人。QQ的衰落集中表现为月活数的下滑。QQ在IM领域是当之无愧的头号玩家,而即时通讯软件成败的关键就在于活跃的用户基数,连年下滑的月活数拖垮了QQ。2016年二季度QQ月活就达到8.99亿,自2017年开始出现连续下滑迹象,此后两年,QQ的月活一直徘徊在8亿左右。至2019年一季度QQ的月活是8.23亿,而2020年一季度QQ的月活仅为6.94亿,一年时间跌了近1.3亿用户。至2021年一季度QQ的月活仅为6.06亿,一年时间再次跌去近9000万用户。而今年二季度QQ月活为5.91亿,至三季度,QQ的月活已经跌至5.74亿。换句话说,在2021年前三季度,QQ每季度平均跌掉1600万用户。从QQ连年下跌的月活来看,这一数据似乎还有下跌空间。微博的衰落表现在营收和净利的增长上。从微博历年财报来看,微博陷入了增长瓶颈。2018年-2020年微博总营收分别为17.19亿美元、17.67亿美元、16.9亿美元,增速分别为49.4%、2.8%、-4.4%;年净利润分别为5.73亿美元、4.93亿美元、3.15亿美元,增速分别为63.7%、-14%、-36%。这三年里微博的营收和净利润都不容乐观。陌陌的衰落体现在无力发展上。截止2021年第二季度,陌陌虽然已经持续26个季度盈利,但是用户数据的下滑坐实了陌陌的衰落。对陌陌而言,生存不是问题,发展才是问题。陌陌的月活和付费率都在失速。从2018年二季度开始,陌陌的月活同比增速就持续下滑,到2019年第四季度,陌陌的月活同比增速仅为1%。2020年第一季度,陌陌的月活直接进入负增长状态。付费用户同比增速也从2018年第三季度开始接连下滑,2020年一季度陌陌的付费用户同比减少120万。这也导致陌陌营收和净利双双下滑。从2020年第一季度到2021第二季度,陌陌的营收已经连续五个季度下滑。其中,2021年第一季度净营收同比下降3.4%,归属于陌陌公司的净利润同比下降14.3%。无论是用户持续减少的QQ,还是营收净利不断下滑的微博,抑或是发展乏力的陌陌都失去了想象空间,三大社交软件不约而同地走上了下坡路。QQ:学不会的断舍离QQ虽然完成了从PC时代向移动时代的跨越,但是却没学到新时代的“断舍离”观念。当然QQ也有做过减法,但是并没有从根本上解决问题,也未能调动优秀产品的活力。一方面,QQ摆脱不了PC端的包袱。PC时代见证了QQ的黄金十年,它无疑是PC时代最成功的社交产品。但时代的洪流滚滚向前,保留PC时代特征的QQ并不一定适合变化越来越快的移动时代。其一,缺乏移动IM的逻辑。移动互联网环境下,不管用户是否在线,软件都会默认用户永远在线,这也是移动IM的重要逻辑。而QQ的“离线、在线、隐身”等状态是PC时代的特性,至今仍保持着这一功能。PC时代的产品特点与移动时代的逻辑有所冲突,这一产品矛盾或许让QQ离用户需求越来越远。其二,臃肿的产品体系让其丢失了老年群体和办公场景。“大而全”是PC时代互联网产品的呈现方式,而移动时代更需要精而简。QQ所推出的厘米秀、微视、兴趣部落、QQ看点等功能让QQ的产品过重,各种花里胡哨的功能加剧了老年群体和办公群体的用户流失。从老年群体角度来看,QQ功能繁多,不易操作,而他们对新事物的接受能力较弱,面对功能复杂的QQ就只能绕道而行。从职场群体角度来看,QQ的信息驳杂,页面杂乱,极大地影响了办公效率,而钉钉等软件的兴起也取代了QQ的办公场景。最为重要的是,QQ的“年轻化”战略也让其贴上了“低龄化”的标签,越来越多的80后、90后出走QQ。另一方面,QQ的附属产品没有发挥出应有的价值。QQ在发展的过程中开发了一系列的附属产品,包括QQ空间、QQ农场、QQ钱包等玩法。这些附属产品对于早期的QQ而言,有完善生态的作用,也有各自的高光时刻,但无法持续为QQ的事业发光发热。拿QQ钱包来看,QQ钱包缺乏生活支付场景,难发挥支付价值。冲Q币、冲会员等形式是QQ钱包最早的消费场景,此后QQ就在“游戏、二次元、直播”等娱乐场景上狂奔。而其他选手早已发力生活场景,成为重要支付方式之一,比如微信支付、支付宝等。QQ也因缺乏生活支付场景而无法跻身到支付领域中去,难以满足用户的支付需求。微博:自我束缚微博的危机源于不吸取教训,任凭流量裹挟平台,将自己置于险地。首先,微博没有找到新的增长引擎。微博的营收业务分为广告业务和增值业务两部分,但从微博近年财报可以看出,微博每年的广告业务占总营收的九成左右。这意味着,微博下一步的发展还要继续依赖广告收入的增长,但广告业务的不稳定因素还有很多。其次,微博的走向正在偏离社交媒体的轨道。社交媒体是人们彼此之间用来分享意见、见解、经验和观点的平台,让普罗大众关注到公共事务,并为此表达自己的看法,参与社会事务之中。这也是新浪微博能够打赢其他三大微博玩家的原因,而现在微博正在丢掉它的优势。一是变了味的热搜。常听人戏称:微博养活新浪,热搜养活微博,买卖热搜已经不是秘密了。据财经天下周刊报道,热搜三条的刊例价为100万左右;开屏的价格在200-300万左右,这还是一天的价格。热搜不再是报道时事,而是有钱就能上,比如2018年“紫光阁地沟油”的热搜闹剧,热搜早就不是关注时事的地方了。二是失了控的饭圈经济。饭圈经济为微博的营收带来巨大贡献,但失控的饭圈也让微博无力招架。在微博上,为了自己的爱豆谩骂互撕是常有的事,比如227事件;而为爱豆氪金打榜也不足为奇,比如周杰伦和蔡徐坤的粉丝打榜大战、“倒奶”事件。饭圈经济让微博多了几分乌烟,也在不断挤出其他用户群体。三是监管不到位。众所周知,微博不生产内容,只是内容发布的审核方。既然微博有审核之责,理应严格审查发布在平台上的信息,合理筛选公共信息,去虚留真。而微博并没有吸取早年“大V入狱”事件的教训,再一次变成舆论的操纵场和虚假消息的发源地。微博的生态在恶化,让用户的体验越来越差。用户无法从微博获得想要的公共信息,反而被种种乱象包裹,自然会迁徙到其他社交媒体平台。最后,失败的打法在直播领域和短视频领域败北。微博早在2013年就看到了短视频风口,投资一下科技,到给予秒拍流量扶持,都彰显着微博的短视频野心。但是,秒拍趋向微博的中心化思维,根本抓不住用户的眼球,而抖快依靠去中心化蹿红后,秒拍毫无招架之力。之后微博也推出多款短视频应用,但风口已逝,即使重启微博视频号也没能激起水花。陌陌:扶不起的社交业务虽然陌陌的创始人始终强调陌陌是个社交平台,但从其营收结构来看,仅占三成营收的社交业务并不能撑起陌陌的商业化野心,陌陌在一点点丢掉社交基本盘。一来鱼龙混杂的社交挫伤了用户的积极性。陌生人社交的门槛本就不高,一旦对平台用户疏于管理,各种问题也就悄然而来。平台内男性用户的骚扰让女性用户逃离陌陌,失去了女性用户,男性用户自然会对平台失去信心。二来广撒网战略也不能为陌陌留住用户。陌陌推出了是他、瞧瞧、Cue、赫兹、ZAO、对对等多款社交产品,试图从多维度挤进社交领域,但多元的社交产品矩阵也没能在社交市场激起水花,唯一爆火的ZAO也因为网络数据安全问题而迅速暴毙。除了自己孵化的APP没能为陌陌带来助力,收购的探探也成了陌陌的拖累。自完成收购后,探探的付费用户增长极其有限。数据显示,探探的付费用户占陌陌总体付费中的26.7%-35.7%。换言之,探探付费用户的增减直接影响陌陌的营收。虽然探探的亏损在收窄,但三年来都处于亏损状态的探探拉低了陌陌的净利润增长。三来陌生人社交本身的流量已经接近尾声。随着互联网交友的方式多元化,用户对交友平台的选择也更加多元化。在各种各样的社交模式冲击下,传统的陌生人交友形式已经不再具有吸引力。而疫情也缩减了陌生人交友的需求,加速了陌陌社交业务的溃败。陌陌疏于管理的社交业务滋生出种种乱象,既催生了其他陌生人社交平台的崛起,又加速了平台流量的流失。时代洗礼22岁的QQ与11岁的微博和陌陌共同走过了移动社交时代、视频社交时代,现在正在迈向虚拟社交时代。前两场社交厮杀,它们平稳渡过,但现在沉疴缠身的它们还能顺利挺过第三场厮杀吗?移动社交时代:微信抢人微信诞生之初既是为了对抗米聊对QQ的冲击,也是为了拓展腾讯的社交群体。后来,微信不仅打败了米聊,也成了其他社交产品的噩梦。对于即时通讯软件来说,简单就是最大的成功。彼时的QQ经过十余年的积累,为用户提供的功能越来越多,却让不少中老年群体无从下手。于是,操作简单、界面简单的微信让社交也变得简单起来。直白的聊天方式赢得了老年人以及职场人士的喜爱。随着微信对熟人社交关系链的沉淀,以亲人、朋友、同事等为核心的熟人社交让用户们不得不留在微信或转投微信,加剧了QQ用户流失。而微信又逐渐发展成一款生活综合软件,集支付、出行、防疫等功能于一体,实现了生活场景的全覆盖,进一步带走QQ用户。对微博来说2013年是最难忘的一年,但这都要从2012年微信推出微信公众平台功能说起。当微信高调地成为移动社交赛道的焦点后,越来越多的微博大V、名人开通自己的微信公众平台,一头扎进熟人社交关系中,通过公众号写作来吸引用户,走向自媒体道路。据《中国互联网络发展状况统计报告》显示,2013年,微博用户下滑了22.8%,微博产品的使用时间仅增加了12.7%。截至2013年年底,手机微博用户数为1.96亿,较2012年年底减少了596万。同时,手机微博的使用率仅为39.3%,比2012年底降低了8.9个百分点。在互联网渗透期的2003年,微博的用户使用率接连下滑,对微博的打击不可谓不小。对陌陌来说,微信简直就是悬在头顶的剑。2011年8月4日陌陌上线,而微信8月3号上线LBS功能——附近的人。微信除了给陌陌带来压迫感,也给陌陌带来了不可逆的用户流失。当两个陌生人在陌陌上聊得非常投机,已经发展出稳定的社交关系后,自然会转向熟人社交,进而流入微信,彻底进入熟人社交阶段,陌陌的活跃用户就面临彻底流失。在陌生人关系转化中,陌陌成了导流工具,微信的熟人社交反而成了最大赢家。视频社交时代:视频平台抢用户时长当流量红利已经见顶,用户时长成了互联网赛事里争夺的焦点。纵观这场赛事,抖音、快手、B站等视频平台成了用户停留最久的软件。据极光大数据显示,2021年Q3快手用户日使用时长均值达到125.3分钟,同比增长30.9%,而抖音的日使用时长均值更是达到144.6分钟。另据QuestMobil统计显示,2019年3月,移动社交、短视频的日均使用时长分别是982亿分钟、358亿分钟;到了今年6月,这两个数字依次为953亿分钟、888亿分钟,短视频的用户时长实现了148%的增长。由数据可知,用户们每天有两个多小时都在刷短视频,短视频占据了人们越来越多的时间。而据《娱乐传媒行业深度报告》显示,QQ 用户时长从约50分钟降至30分钟左右。QQ不仅留不住用户,连用户时长也逐渐下滑,最后只剩下满是记忆的通讯录。而微博的用户时长也更不容乐观。据易观千帆统计显示,2019年5月-2020年4月,微博月均用户使用时长在10小时上下徘徊,换算下来,用户平均一天使用时长20分钟,相比于抖、快的用户时长相距甚远,并且根据走势来看,微博的日均用户使用时长还在下降。微博丢掉的不仅是用户时长,还有广告业务。据微博招股书披露,其广告客户数量也在不断下滑,2018年-2020年微博的广告客户数量分别为290万、160万、240万。至今年6月,微博的广告主已经腰斩至60万。在社交赛道里,不仅微博的商业化受到短视频平台的阻击,短视频平台也在蚕食着陌陌的商业能力。陌陌目前的主要营收来自秀场直播业务,这势必需要大量美女主播,但抖、快两大平台巨大的流量与超强的印钞能力也抢走了陌陌的主播资源。据媒体报道,受到疫情和抖音对主播大力扶植的影响,陌陌旗下的主播40%都出走抖音。互联网公司的变现方式无外乎广告业务、增值业务、付费业务这几类,但在格局已定的情况下,短视频平台想要分一杯羹,就需要从其他玩家身上割下来几块肉,不幸的是,QQ、微博、陌陌这三位社交赛道细分领域的头部玩家率先成为被割肉的对象。虚拟社交时代:社交元宇宙成劲敌社交赛道总有新玩法,随着扎克伯格将Facebook集团名字换成“Meta”,再次将社交元宇宙推上新高度。而国内也早已涉及社交元宇宙。比如主打灵魂社交的Soul、百度推出的希壤等社交元宇宙玩法正在重塑社交赛道的话语权,这无疑会冲击老牌社交平台。其实,社交元宇宙最大的优势就是虚拟化。每个用户在社交中都有一个虚拟身份,不用顾虑现实社交中存在的种种问题,将现实生活与社交元宇宙分割开来。社交元宇宙平台依托5G、XR、实时互联网等技术,辅以游戏等多元玩法,为用户打造一种沉浸式虚拟社交,给用户圈画出一个理想世界。社交元宇宙正在成为社交的新宠,比如国内社交元宇宙黑马Soul已经展现出强劲的活力。据Soul的招股书显示,Soul的DAU已达千万量级,同比增长94.4%。Soul 的日均DAU打开次数为24次,为行业最高。从2020年7月开始至今,Soul每月的MAU用户增长速度,平均保持在105%以上。而在用户粘性上,2021年3月,每月活跃天数超15天的比例达56.4%。2020年12月活跃超15天的用户中,有78.4%的用户在三个月后仍维持同样的活跃度。另招股书显示,2019年到2021年一季度,Soul营收分别为7070万元、4.98亿元、2.38亿元,2020年的营收在同比增长604.3%的情况下,今年第一季度同比再增长260%。Soul以一种强劲的增长势能正在创造社交新焦点。QQ、微博、陌陌:逃不出社交命QQ、微博和陌陌各自代表着社交细分赛道的牌面,一路走来风浪无数,但都顽强存活下来了。QQ尝试定位年轻化,拉动月活增长。微博和陌陌尝试转型多元化,探索更加健康的商业结构。这表明,它们并非坐以待毙,只是目前都没有太大成效。那么,QQ、微博、陌陌的社交命运,到底该何去何从呢?一是如早期的社交先烈们一般留在回忆中。偷菜、抢车位的开心网,“找同学,上人人”的人人网,无一不是社交赛道的佼佼者,都有过各自的辉煌年代。但太阳总会有下山的时候,无论散发着多耀眼的光芒,也会从西边落下。开心网和人人网成为80后和90后的美好回忆,QQ、微博、陌陌也会成为一代人的回忆。二是主动出击,扳回一城。在玩法新奇、对手林立的社交赛道,QQ、微博、陌陌等老玩家想要继续占据一席之地,势必要一改过去的防守状态,以攻代守,改变自身的被动局面。纵观社交赛道的形态变化,经历了从基础社交到内容社交再到精神社交的演变。这表明,用户需求并不局限于已有的社会性社交,而是转向具有新意的“下一代社交”。“下一代社交”需要依托技术,帮助所有人摆脱传统的“中国式孤独”,在任何语境下都给用户带来愉悦的精神享受。对于QQ、微博、陌陌来说,在基于用户心理的情况下,依托技术来建立新的社交关系,在满足用户基础社交体验之外,也考虑到用户的心理需求。或许,通过对平台的精细化运营,能够完成对存量用户的争夺,以及对沉默用户的召回。
BBS论坛(二十)
20.1.cms添加轮播图后台逻辑代码完成(1)apps/models.py代码语言:javascript复制from exts import db
from datetime import datetime
class BannerModel(db.Model):
__tablename__ = 'banner'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(255), nullable=False)
img_url = db.Column(db.String(255), nullable=False)
link_url = db.Column(db.String(255), nullable=False)
priority = db.Column(db.Integer, default=0)
create_time = db.Column(db.DateTime, default=datetime.now)(2)manage.py代码语言:javascript复制from apps.models import BannerModel(3)生成到数据库代码语言:javascript复制python manage.py db migrate
python manage.py db upgrade(4)cms/forms.py代码语言:javascript复制class AddBannerForm(BaseForm):
name=StringField(validators=[InputRequired(message='请输入轮播图名称')])
img_url=StringField(validators=[InputRequired(message='请输入轮播图链接')])
link_url=StringField(validators=[InputRequired(message='请输入轮播图跳转链接')])
priority=IntegerField(validators=[InputRequired(message='请输入轮播图优先级')])(5)cms/views.py代码语言:javascript复制@bp.route('/abanner/',methods=['POST'])
def abanner():
form=AddBannerForm(request.form)
if form.validate():
name=form.name.data
img_url=form.img_url.data
link_url=form.link_url.data
priority=form.priority.data
banner=BannerModel(name=name,img_url=img_url,link_url=link_url,priority=priority)
db.session.add(banner)
db.session.commit()
return restful.success()
else:
return restful.params_error(message=form.get_error())20.2.cms添加轮播图前台逻辑完成(1)cms/js/banner.js代码语言:javascript复制$(function () {
$('#save_banner_btn').click(function (event) {
event.preventDefault();
var dialog = $('#banner-dialog');
var nameInput = $("input[name='name']");
var imgInput = $("input[name='img_url']");
var linkInput = $("input[name='link_url']");
var priorityInput = $("input[name='priority']");
var name = nameInput.val();
var img_url = imgInput.val();
var link_url = linkInput.val();
var priority = priorityInput.val();
if (!name || !img_url || !link_url || !priority) {
zlalert.alertInfo('请输入完整的轮播图数据');
return;
}
zlajax.post({
'url': '/cms/abanner/',
'data': {
'name': name,
'img_url': img_url,
'link_url': link_url,
'priority': priority
},
'success': function (data) {
if (data['code'] == 200) {
dialog.modal('hide');
window.location.reload()
} else {
zlalert.alertInfo(data['message']);
}
},
'fail': function (error) {
zlalert.alertNetworkError()
}
});
});
});(2)cms/cms_banners.html代码语言:javascript复制{% from 'common/_macros.html' import static %}
<script src="{{ static('cms/js/banners.js') }}"></script>(3)cms/views.py代码语言:javascript复制@bp.route('/banners/')
@login_required
def banners():
banners = BannerModel.query.all()
return render_template('cms/cms_banners.html',banners=banners)(4)cms_banners.html代码语言:javascript复制<tbody>
{% for banner in banners %}
<tr>
<td>{{ banner.name }}</td>
<td><a href="{{ banner.img_url }}" target="_blank">{{ banner.img_url }}</a></td>
<td><a href="{{ banner.link_url }}" target="_blank">{{ banner.link_url }}</a></td>
<td>{{ banner.priority }}</td>
<td>{{ banner.create_time }}</td>
<td>
<button class="btn btn-default btn-xs edit-banner-btn">编辑</button>
<button class="btn btn-danger btn-xs delete-banner-btn">删除</button>
</td>
</tr>
{% endfor %}
</tbody>
BBS论坛(十八)
18.首页轮播图实现(1)front/css/front_base.css代码语言:javascript复制.main-container{
width: 990px;
margin: 0 auto;
overflow: hidden;
}
.lg-container{
width: 730px;
float:left;
}
.sm-container{
width: 250px;
float:right;
}(2)front_base.html代码语言:javascript复制<link rel="stylesheet" href="{{ url_for('static',filename='front/css/front_base.css') }}">
<div class="main-container">
{% block body %}
{% endblock %}
</div>(3)front_index.html代码语言:javascript复制{% extends "front/front_base.html" %}
{% block title %}
仙剑论坛
{% endblock %}
{% block head %}
<link rel="stylesheet" href="{{ static('front/css/front_index.css') }}">
{% endblock %}
{% block body %}
<div class="lg-container">
<div id="carousel-example-generic" class="carousel slide index-banner" data-ride="carousel">
<!-- 指示器 -->
<ol class="carousel-indicators">
<li data-target="#carousel-example-generic" data-slide-to="0" class="active"></li>
<li data-target="#carousel-example-generic" data-slide-to="1"></li>
<li data-target="#carousel-example-generic" data-slide-to="2"></li>
</ol>
<!-- 轮播图-->
<div class="carousel-inner" role="listbox">
<div class="item active">
<img src="https://static-image.xfz.cn/1512989310_955.jpg" alt="...">
<div class="carousel-caption">
...
</div>
</div>
<div class="item">
<img src="https://static-image.xfz.cn/1528079965_535.jpeg" alt="...">
<div class="carousel-caption">
...
</div>
</div>
...
</div>
<!-- Controls -->
<a class="left carousel-control" href="#carousel-example-generic" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="right carousel-control" href="#carousel-example-generic" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
</div>
<div class="sm-container">
</div>
{% endblock %}(4)front/css/front_index.css代码语言:javascript复制.index-banner{
border-radius: 10px;
overflow: hidden;
height: 190px;
}
.index-banner img{
height: 190px;
}
#自媒体#新媒体课堂——自媒体平台知多少?自媒体平台有哪些?
自媒体带起了一波创业者的高潮,做自媒体的主要就是两类人,要么是为了流量,获得用户关注;要么是为了阅读量,广告变现。说白了就是为了名利!有很多人都想做自媒体,但是该怎么做才好呢?做自媒体,写文章虽然重要,但是发文章比写重要10倍以上,只有让更多的人看到你的文章,你的文章才能给你带来更大的价值,一篇文章写出来,你发的平台不对,也不行。今天知道君整理了一些可以免费注册与发布的自媒体平台,如果你把文章发布到这些自媒体平台,你的每篇文章最少都有几万人看到,效果怎么样, 就不用多说了。现在直接分享给大家:微信公众平台微信公众平台,给个人、企业和组织提供业务服务与用户管理能力的全新服务平台。… 给企业和组织提供更强大的业务服务与用户管理能力,帮助企业快速实现全新的公众号服务平台是否免费:免费操作难度:简单应用类型:全部应用网址:http://mp.weixin.qq.com今日头条今日头条是一款基于数据挖掘的推荐引擎产品,它为用户推荐有价值的、个性化的信息,提供连接人与信息的新型服务,是国内移动互联网领域成长最快的产品服务之一是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.toutiao.com/百度百家百家是百度新闻的原创内容类平台。每日发布的优质内容将会在百度新闻的网页版、移动端呈现,并被百度搜索和百度其他产品线收录。是否免费:免费操作难度:简单应用类型:全部应用网址:http://baijia.baidu.com/搜狐媒体平台搜狐媒体平台是在搜狐门户改革背景下全新打造的内容发布和分类分发全平台。各个行业的优质内容供给者(媒体、自媒体)均可免费申请入驻,为搜狐提供内容;利用搜狐强大的媒体影响力,入驻媒体和自媒体可获取自己的用户,提升个人的品牌影响力是否免费:免费操作难度:简单应用类型:全部应用网址:http://mp.sohu.com/一点资讯一点资讯是一款高度智能的新闻资讯应用,通过它你可以搜索并订阅任意关键词,它会自动帮你聚合整理并实时更新相关资讯,同时会智能分析你的兴趣爱好,为你推荐感兴趣的内容。看新闻资讯,一点就够了!是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.yidianzixun.com/网易媒体平台网易订阅,聚合旅游、时尚、财经、科技资讯、时事新闻、RSS等众多内容,提供个性化的阅读服务是否免费:免费操作难度:简单应用类型:全部应用网址:http://dy.163.com/wemedia/login.html企鹅媒体平台企鹅媒体平台是2016年3月1日,企鹅媒体平台正式推出,腾讯将提供四个方面的能力。是否免费:免费操作难度:简单应用类型:全部应用网址:https://om.qq.com/userAuth/index北京时间号北京时间互联网门户全新领导者,依托强大的推荐引擎与专业的媒体人团队为用户实时呈现最具价值的新鲜资讯。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.btime.com/QQ公众号QQ公众平台聚合着无限可能。凭借16年来积累的8亿用户资源,依托强势平台技术、数据沉淀和社交关系,QQ公众平台将有效聚集品牌和消费者,以开放合作的姿态与你一起打造未来。是否免费:免费操作难度:简单应用类型:全部应用网址:http://mp.qq.com/凤凰自媒体“凤凰自媒体”正式更名为“凤凰号”。据了解,凤凰自媒体平台更名后,希望能加快品牌特色化进程,深耕高质量内容领域,由此形成行业差异化竞争格局,实现优质文章在凤凰新闻客户端、凤凰网、手机凤凰网、凤凰视频客户端等渠道的有效分发。是否免费:免费操作难度:简单应用类型:全部应用网址:http://fhh.ifeng.com/login大鱼号大鱼号是阿里文娱体系为内容创作者提供的统一账号。大鱼号实现了阿里文娱体系一点接入,多点分发。内容创作者一点接入大鱼号,上传图文/视频可被分发到UC、优酷、土豆、淘系客户端,未来还会扩展到豌豆荚、神马搜索、PP助手等。是否免费:免费操作难度:简单应用类型:全部应用网址:http://mp.uc.cn/index.html知乎一个真实的网络问答社区,帮助你寻找答案,分享知识。..是否免费:免费操作难度:简单应用类型:全部应用网址:https://www.zhihu.com/钛媒体【钛媒体官方网站】钛媒体是国内首家TMT公司人社群媒体,最有钛度的一人一媒体平台,集信息交流融合、IT技术信息、新媒体于一身的媒体平台。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.tmtpost.com/LIKE.TG+社区LIKE.TG最新又推出了一款扶持计划-『自媒体分享计划』满足条件的自媒体,入驻LIKE.TG+社区,可分享总价值百万资源包是否免费:免费操作难度:困难应用类型:全部应用网址:https://cloud.tencent.com/developer/support-plan?invite_code=oc38tj48tn8qhttp://www.tmtpost.com/虎嗅网聚合优质的创新信息与人群,捕获精选|深度|犀利的商业科技资讯。在虎嗅,不错过互联网的每个重要时刻。是否免费:免费操作难度:简单应用类型:全部应用网址:https://www.huxiu.com/砍柴网砍柴网创立于2013年,是一家拥有全球视野的前沿科技媒体,我们始终秉承观点独到、全面深入、有料有趣的宗旨,在科技与人文之间寻找商业新价值,坚持以人文的视角解读科技,用专业的精神剖析时代,孜孜不倦探索科技与商业的未来。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.ikanchai.com/i黑马i黑马是面向创业者的创新型综合服务平台,掌握创业创新领域强有力话语权的媒体矩阵,致力于帮助创业者获得投资、人才、宣传和经验。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.iheima.com/雷锋网雷锋网是国内最早关注人工智能和智能硬件领域的互联网科技媒体,内容涵盖人工智能、智能硬件、机器人、智能驾驶、ARVR、网络安全、物联网、未来医疗、金融科技等9大领域。雷锋网致力于连接和服务学术界、工业界与投资界,为用户提供更专业的互联网科技资讯和培训服务,让用户读懂智能与未来。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.leiphone.com/猎云网猎云网坚守用心服务创业者的理念,专注创业创新,互联网创业项目推荐,关注新产品、新公司、新模式,以原创独家报道、分析以及美国硅谷的一手报道闻名业界。为创业者、投资人及相关业内人士提供交流学习、资源对接的桥梁。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.lieyunwang.com/锌媒体锌媒体是一个关注前沿科技资讯、移动互联网,发现以及商业创新价值的泛科技自媒体平台。精选最新科技新闻,分享即时的移动互联网行业动态和以及提供最具商业价值的互联网创业案例,投资案例。提供绝对给力的干货、,在科技与人文之间挖掘商业新价值。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.xinmeti.com/派代网派代网定位为中国电子商务的入口,目前是中国最活跃、最具影响力的电子商务行业交流平台,聚集了大量的电子商务领军企业创始人群。提供电商学习、人才招聘、企业贷款等电子商务综合服务。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.paidai.com/简书致力于开发维护一套集合文字的书写、编集、发布功能于一体的在线写作编辑工具是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.jianshu.com/亿欧网亿欧是一家专注于新科技、新理念与各产业结合,以助力产业创新升级为使命的服务平台。亿欧旗下有4款产品,分别是亿欧网、视也、天窗、企服盒子。自2014年2月9日开始运营后,迅速成为互联网创业者和产业创新者的首选学习平台,是上百家知名企业的首选商业合作伙伴;先后获得盈动资本、高榕资本、盛景网联领投的三轮融资是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.iyiou.com/思达派思达派是专注创业服务市场的新媒体平台,定位“创业干货分享”,一站集成创业经验、教训等干货,帮助创业者少走弯路。同时还将举办各种线下创业分享和交流活动,分享创业心得,对接人脉、资本、以及公关推广等资源。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.startup-partner.com/界面界面是最受中国中产阶级欢迎的新闻及商业社交平台,旗下拥有精品新闻业务界面新闻、专业投资资讯平台摩尔金融及中国最大独立设计师电商网站尤物。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.jiemian.com/爱范儿聚焦新创和消费主题的科技媒体,成立于 2008 年 10 月,关注产品及体验,致力于“独立,前瞻,深入”的原创报道和分析评论,是国内唯一一家在产业和产品领域同时具有强势影响力的科技媒体。旗下现有 ifanr.com、SocialBase.cn、AppSolution、玩物志、创业及产品社区 MindStore 等多个细分领域的知名产品。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.ifanr.com/36氪36氪为您提供创业资讯、科技新闻、投融资对接、股权投资、极速融资等创业服务,致力成为创业者可以依赖的创业服务平台,为创业者提供最好的产品和服务。是否免费:免费操作难度:简单应用类型:全部应用网址:http://36kr.com如果一篇文章在一个平台一天有100个阅读量,在50个平台上就是5000阅读,那么10天呢,一年356天呢,可能前期会辛苦一点,但是你需要坚持,越到后面,你在互联网上发布的文章越多,加你的人也会越多,而且这些文章将会在多年以后都能够继续为你带来流量,有的人两年前写的文章,现在还有人看了还会加v信。外加两个,趣头条,惠头条。有的人可能会问,这么多平台,发文章比写文章还累!额。。。。。。你需要学会找工具,早就有人开发出来了一键发布功能,一篇文章可以同时发布到多个自媒体平台上!什么工具呢?百度一下,你就知道!以上,是今天给大家提供的一些思路,希望对大家有帮助!这些仅仅是各大门户网站的自媒体开放平台,没有精确到各种类型的全部平台,如小视频类app、综合视频类网站都没有开始说,由于篇幅的原因,留到以后再进行补充吧。
RT论坛_Thread
大家好,又见面了,我是你们的朋友全栈君。
文章主要参考:https://blog.csdn.net/killercode11/article/details/104290949,借鉴了rt_hw_console_getchar()的定义。
文章目录将 FinSH源码添加到工程开启 FinSH定义终端读取函数体验 FinSH遇到的问题 本文不介绍 RT-Thread 的串口配置,如有需要,可以参考:重映射串口到 rt_kprintf 函数
将 FinSH源码添加到工程FinSH源码在 RT-Thread 源码目录的 components\finsh\ 目录下,将其导入到工程中,具体操作这里不做介绍,记得要把头文件包含进来,开启 FinSH修改 rtconfig.h,开启 finsh config,下面是使用 Configuration Wizard 向导进行图形化配置,
其实就是将 finsh_fonfig.h 头文件包含到工程中,这个头文件里有 FisSH 的基本参数配置,定义终端读取函数移植完 FinSH 源码后,初次编译一般会报一个错误,需要将弱化函数 rt_hw_console_getchar() 里的 #error 这行屏蔽掉(记得先把该文件的只读属性关闭)
接着我们在 board.c 文件手动重新定义 rt_hw_console_getchar() 函数,函数内容如下,这是标准库版本,如果需要 HAL库版本,可以参考文章最前面的链接。代码语言:javascript复制char rt_hw_console_getchar(void)
{
/* Note: the initial value of ch must < 0 */
int ch = -1;
if(USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) != RESET)
{
//USART_ClearITPendingBit(USART_DEBUG, USART_FLAG_RXNE);
ch = USART_ReceiveData(DEBUG_USARTx) 0xFF;
}
else
{
if(USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_ORE) != RESET)
{
USART_ClearITPendingBit(DEBUG_USARTx, USART_FLAG_ORE);
}
rt_thread_mdelay(10);
}
return ch;
} Jetbrains全家桶1年46,售后保障稳定 体验 FinSH我使用 SSCOM 来作为终端,效果还不错,命令直接在显示窗口里输入。
或许有人会问为什么不用 PuTTy、XShell 这类常用的终端软件,我也想用,但连接上这类终端软件后,开发板就不运行了。遇到的问题1.段错误导致这种错误的原因有很多种,比如 RT_MAIN_THREAD_STACK_SIZE 太小,而我是因为 RT_THREAD_PRIORITY_MAX 设置得太小(只设置为 8),小于 FINSH_THREAD_PRIORITY 的默认值 21,所以解决办法就是将 FINSH 的线程优先级(数值)改小或者将系统优先级最大值(数值范围)改大。2.终端工具无法打印使用 PuTTy、XShell,终端没反应,且开发板会卡住。初步分析的原因是 “正点原子一键下载电路和终端工具冲突”(网上他人结论),所以只能用串口调试助手来操作 Finsh 了。3.程序不运行这个问题可能的原因也很多,但需要注意的是:如果要使用 FinSH,就不能开启串口中断,至于为什么,我目前也没去了解。版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。 发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/210436.html原文链接:https://javaforall.cn
徐大大seo:创建外链 的7种有效方法
外链是指其他网站链接到你的网站,这对于提高网站的权威性和排名非常重要。但是,如何创建有效的外链呢?下面介绍7种有效的方法。1. 内容质量内容是吸引外链的关键。如果你的内容质量高,其他网站自然会愿意链接到你的网站。因此,要确保你的内容有价值、有趣、有吸引力,这样才能吸引其他网站链接到你的网站。2. 社交媒体社交媒体是一个非常有效的外链来源。你可以在社交媒体上分享你的内容,并引导用户访问你的网站。此外,你还可以与其他网站建立联系,互相分享内容,这样可以增加你的外链数量。3. 博客评论博客评论是另一个有效的外链来源。你可以在其他博客上留下评论,并在评论中包含你的网站链接。这样可以吸引其他博客的读者访问你的网站,并增加你的外链数量。4. 媒体报道如果你的网站被媒体报道,这将是一个非常好的外链来源。你可以在媒体报道中包含你的网站链接,这样可以吸引更多的用户访问你的网站,并提高你的网站权威性。5. 参与论坛参与论坛是另一个有效的外链来源。你可以在相关论坛上留下评论,并在评论中包含你的网站链接。这样可以吸引其他论坛用户访问你的网站,并增加你的外链数量。6. 搜索引擎优化搜索引擎优化是提高网站排名和权威性的关键。你可以通过优化你的网站内容和结构,使其更容易被搜索引擎识别和收录。这样可以提高你的网站排名和权威性,从而吸引更多的外链。7. 建立联系最后,建立联系是创建有效外链的关键。你可以与其他网站建立联系,互相分享内容,并在彼此的网站上包含链接。这样可以增加你的外链数量,并提高你的网站权威性。总之,创建有效的外链需要一定的时间和努力。但是,如果你能够遵循上述方法,你的网站将会受益匪浅。
spring 论坛 顶
http://bbs.springcloud.com.cn/ http://blog.didispace.com/spring_cloud_community/https://eacdy.gitbooks.io/spring-cloud-book/content 使用Spring Cloud与Docker实战微服务http://ask.itmuch.com/http://www.kailing.pub/index/columns/colid/10.html快捷键说明 各种工具的http://mykeys.sinaapp.com/index.phphttps://jhipster.github.io/jHipster(J潮客)其亮点:风头超劲,席卷欧美,最新全能Java Web开发程式产生器 (java web generator)。由Java专家累积的开发经验,配上各类实用的框架技术,去繁取精的运用,全方位的配置,制成出完备的开发应用程式。完美Java体系架构,适合各行各业项目,尤其以适用于面向服务的体系结构(SOA)更为胜任。不论菜鸟,老牛或专家,极容易上手,只要你可以下载及建立以下要求的工作环境。快速建成一个制作就绪的基本项目工作模版,令你可以用有限的精力专注业务上的运作。制作例子包括:jHipster3.4+Spring4.2.6+Spring Boot1.3.5+Hibernate4.3.11+MySQL5.7.12+AngularJs1.5.5https://cloud.tencent.com/developer/support-plan?invite_code=1zx789a2fog08
论坛
LAMP架构:Linux+Apache+Mysql+PHP官方网站:http://www.mysql.com/http://dev.mysql.com/downloads/mysql/CentOS 7.0中,已经使用MariaDB替代了MySQL数据库,原因你懂的,MYSQL被Oracle收购以后,前景堪忧,所以MYSQL兄弟MariaDB就出来了,继续开源事业。以rpm包的方式安装LAMP。一、安装需要的软件包[root@docker-04 ~]# yum -y install httpd mariadb-server mariadb php php-mysqlcentos6.5执行以下[root@docker-04 ~]# yum install httpd mysql-server mysql php php-mysql -yhttpd # web服务器mariadb-server #mysql数据库mariadb # mysql服务器linux下客户端php #php相关文件php-mysql #??? #php程序连接mysql使用的模块查看某个命令由哪个包安装[root@docker-04 ~]# rpm -qf `which mysql`mariadb-5.5.60-1.el7_5.x86_64启动服务LAMP相关服务:[root@docker-04 ~]# systemctl start httpd[root@docker-04 ~]# systemctl enable httpd[root@docker-04 ~]# systemctl start mariadb[root@docker-04 ~]# systemctl enable mariadb[root@docker-04 ~]# systemctl status mariadb测试数据库连接:连接mysql数据库,连接本机可以去掉-h #mysql 或:# mysql -h IP -u USER -pPASS Mysql的超级管理员是root拥有最mysql数据库的最高权限。例:# mysql -u root –p123456 –h 10.10.10.68mysql> exit; #退出mysqlMySQL安全配置向导安装完mysql-server 会提示可以运行mysql_secure_installation。运行mysql_secure_installation会执行几个设置: a)为root用户设置密码 b)删除匿名账号 c)取消root用户远程登录 d)删除test库和对test库的访问权限 e)刷新授权表使修改生效通过这几项的设置能够提高mysql库的安全。建议生产环境中mysql安装这完成后一定要运行一次mysql_secure_installation,详细步骤请参看下面的命令:NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MySQLSERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!In order to log into MySQL to secure it, we'll need the currentpassword for the root user. If you've just installed MySQL, andyou haven't set the root password yet, the password will be blank,so you should just press enter here.Enter current password for root (enter for none):<–初次运行直接回车OK, successfully used password, moving on…Setting the root password ensures that nobody can log into the MySQLroot user without the proper authorisation.Set root password? [Y/n] <– 是否设置root用户密码, 刚才我已设置密码,我们输n... skippingBy default, a MySQL installation has an anonymous user, allowing anyoneto log into MySQL without having to have a user account created forthem. This is intended only for testing, and to make the installationgo a bit smoother. You should remove them before moving into aproduction environment.Remove anonymous users? [Y/n] <– 是否删除匿名用户,生产环境建议删除,所以直接回车或Y… Success!Normally, root should only be allowed to connect from 'localhost'. Thisensures that someone cannot guess at the root password from the network.Disallow root login remotely? [Y/n] <–是否禁止root远程登录,根据自己的需求选择Y/n并回车,建议禁止… Success!By default, MySQL comes with a database named 'test' that anyone canaccess. This is also intended only for testing, and should be removedbefore moving into a production environment.Remove test database and access to it? [Y/n] <– 是否删除test数据库,直接回车或Y- Dropping test database…… Success!- Removing privileges on test database…… Success!Reloading the privilege tables will ensure that all changes made so farwill take effect immediately.Reload privilege tables now? [Y/n] <– 是否重新加载权限表,直接回车… Success!Cleaning up…All done! If you've completed all of the above steps, your MySQLinstallation should now be secure.Thanks for using MySQL!如果不做安全配置root密码[root@docker-03 ~]# mysqladmin -u root password “123456"测试:登录mysql [root@docker-03 ~]# mysql -u root -p或:[root@docker-03 ~]# mysql -u root -p123456测试:[root@docker-04 ~]# mysql -u root -p123456mysql> show databases; #没有test数据库#执行时,所有命令以;号结尾+--------------------+ | Database | +--------------------+ | information_schema | | mysql | | ucenter | +--------------------+ 3 rows in set (0.00 sec) mysql> exit #退出命令可以加分号,也可以不加分号。测试网站是否支持PHP # cd /var/www/html/ [root@docker-04 html]# vim index.php<?php phpinfo(); ?> 测试:[root@docker-04 html]# systemctl restart httpd 重启webhttp://172.17.120.53/index.php搭建LAMP环境部署Ucenter和Ucenter-home网站,搭建一个人人网的社交网站www.renren.comUCenter 用户中心,实现用户的统一登录登出,积分的兑换,TAG的互通等,在安装UCenter Home、Discuz!、SupeSite、X-Space 等应用前必须先安装UCenter。本教程讲解的即是如何全新安装UCenter 3.2.0。http://www.discuz.netDiscuz! 论坛,百万站长的选择,定会给您带来非凡的论坛体验。Discuz! 7.0.0 的推出使Discuz! 的用户体验又上升到了一个新的高度。本教程讲解的即是如何全新安装Discuz! 7.0.0 FULL(集成了UCenter 安装的版本)。UCenter Home 个人家园,给社区中的会员一个可以安家的地方,在这里会员可以交朋友,写记录,发日志,贴照片,玩游戏...使会员可以牢牢的黏在你的社区里。本教程讲解的即是如何全新安装UCenter Home 3.2。SupeSite 社区门户,实现CMS 的功能,拥有强大的模型功能,对Discuz! 和UCenter Home 的完美聚合,是您将社区中所有信息进行整合展示的最佳平台。本教程讲解的即是如何全新安装SupeSite到服务器上/opt目录下:[root@docker-04 opt]# wget http://download.comsenz.com/DiscuzX/3.2/Discuz_X3.2_SC_UTF8.zip[root@docker-04 opt]# unzip -d ./ucenter Discuz_X3.2_SC_UTF8.zip # 解压缩到./ucenter [root@docker-04 opt]# cd ./ucenter[root@docker-04 ucenter]# lsreadme upload utility[root@docker-04 ucenter]# mkdir /var/www/html/ucadmin #创建目录[root@docker-04 ucenter]# mv upload/* /var/www/html/ucadmin[root@docker-04 ucenter]# cd /var/www/html/ucadmin[root@docker-04 ucadmin]# lsadmin.php connect.php forum.php member.php search.php uc_serverapi cp.php group.php misc.php source userapp.phpapi.php crossdomain.xml home.php plugin.php staticarchiver data index.php portal.php templateconfig favicon.ico install robots.txt uc_client# robots.txt 网站根目录下,robots.txt 文件作用。Robots协议(也称为爬虫协议、机器人协议等)全称是“网络爬虫排除标准”(Robots Exclusion Protocol),网站通过Robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取。robots.txt文件是一个文本文件,使用任何一个常见的文本编辑器,比如Windows系统自带的Notepad,就可以创建和编辑它[1] 。robots.txt是一个协议,而不是一个命令。robots.txt是搜索引擎中访问网站的时候要查看的第一个文件。robots.txt文件告诉蜘蛛程序在服务器上什么文件是可以被查看的。但robots.txt不是命令,也不是防火墙,如同守门人无法阻止窃贼等恶意闯入者。修改文件权限:[root@docker-04 ucadmin]# ls -ld datadrwxr-xr-x. 13 root root 216 5月 31 2016 data[root@docker-04 ucadmin]# ps -aux | grep httpdroot 18277 0.0 0.1 410156 13540 ? Ss 14:46 0:00 /usr/sbin/http-DFOREGROUNDapache 18279 0.0 0.0 410288 9156 ? S 14:46 0:00 /usr/sbin/http-DFOREGROUNDapache 18280 0.0 0.0 410288 7860 ? S 14:46 0:00 /usr/sbin/http-DFOREGROUND[root@docker-04 ucadmin]# id apacheuid=48(apache) gid=48(apache) 组=48(apache)[root@docker-04 ucadmin]# chown apache:apache data/ -R或:[root@docker-04 ucadmin]# chmod -R 777 data # 为安全正确做法应该是chown –R apache:apache data。后面安装好后测试。安装网站模版:安装UCenter:打开:http://172.17.120.53/ucadmin/install/要安这个打开:[root@docker-04 ucadmin]# vim /etc/php.ini #php运用程序的配置文件改:211 short_open_tag = Off为:211 short_open_tag = On开启PHP短标签功能。决定是否允许使用,代码开始标志的缩写形式(<? 。。。?>)PHP 代码开始标志的完整形式为:<?php。。。?>#重新加载配置文件[root@docker-04 ucadmin]# systemctl restart httpd.service测试:http://172.17.120.53/ucadmin/install/需要这个data目录可写:注:这个注册码很不清楚,多按F5刷新几次就可以了要记录创始人用户名:admin 密码:123456 关于运维学习、分享、交流,笔者开通了微信公众号【运维猫】,感兴趣的朋友可以关注下,欢迎加入,建立属于我们自己的小圈子,一起学运维知识。
BBS论坛(八)
8.1.发送邮箱验证码功能(1)cms/resetemail.html代码语言:javascript复制{% from 'common/_macros.html' import static %}
{% block head %}
<script src="{{ static('cms/js/resetemail.js')}}"></script>
{% endblock %}
<input type="email" name="email" placeholder="新邮箱" class="form-control">
<span class="input-group-addon" id="captcha-btn" style="cursor: pointer">获取验证码</span>(2)cms/js/resetemail.js代码语言:javascript复制/**
* Created by derekon 2018/6/4.
*/
$(function () {
$("#captcha-btn").click(function (event) {
event.preventDefault();
var email = $("input[name='email']").val();
if(!email){
zlalert.alertInfoToast('请输入邮箱');
}
zlajax.get({
'url': '/cms/email_captcha/',
'data': {'email':email},
'success': function (data) {
if(data['code'] == 200){
zlalert.alertSuccessToast('邮件已发送成功!请注意查收!');
}else{
zlalert.alertInfo(data['message']);
}
},
'fail':function (error) {
zlalert.alertNetworkError();
}
});
});
});(3)cms/views.py代码语言:javascript复制@bp.route('/email_captcha/')
def email_captcha():
#获取要修改的邮箱
email = request.args.get('email')
if not email:
return restful.params_error('请输入要修改的邮箱')
#得到大小写字母的列表
source = list(string.ascii_letters)
#得到大小写字母的列表 + 0到9的数字字符串
source.extend(map(lambda x: str(x), range(0, 10)))
# 随机取六位作为验证码
captcha = "".join(random.sample(source, 6))
#给这个邮箱发送邮件验证码
message = Message(subject='derek论坛密码修改邮件发送', recipients=[email,], body='你的验证码是:%s'%captcha)
try:
mail.send(message)
except:
return restful.server_error()
return restful.success()输入邮箱,点“获取验证码”8.2.修改邮箱功能完成(1)utils/zlcache.py把验证码保存到memcached中代码语言:javascript复制# utils/zlcache.py
import memcache
cache = memcache.Client(['139.199.131.146:11211'],debug=True)
def set(key,value,timeout=60): #过期时间60s
return cache.set(key,value,timeout)
def get(key):
return cache.get(key)
def delete(key):
return cache.delete(key)(2)cms/views.py代码语言:javascript复制zlcache.set(email,captcha) 把邮箱和验证码相关联保存到memcached中代码语言:javascript复制@bp.route('/email_captcha/')
def email_captcha():
.
.
.
.
try:
mail.send(message)
except:
return restful.server_error()
#把邮箱和验证码保存到memcached中
zlcache.set(email,captcha)
return restful.success()(3)cms/forms.py代码语言:javascript复制from utils import zlcache
from wtforms import ValidationError
from flask import g
class ResetEmailForm(BaseForm):
email = StringField(validators=[Email(message="请输入正确格式的邮箱")])
captcha = StringField(validators=[Length(min=6,max=6,message='请输入正确的邮箱验证码')])
# 自定义验证
def validate_captcha(self,field):
#form要提交的验证码和邮箱
captcha = field.data
email = self.email.data
#缓存里面保存的邮箱对应的验证码
captcha_cache = zlcache.get(email)
#如果缓存中没有这个验证码,或者缓存中的验证码跟form提交的验证码不相等(不区分大小写)
# 两个有一个不成立,就抛异常
if not captcha_cache or captcha.lower() != captcha_cache.lower():
raise ValidationError('邮箱验证码错误!')
def validate_email(self, field):
email = field.data
user = g.cms_user
if user.email == email:
raise ValidationError('不能修改为当前使用的邮箱!')(4)cms/js/resetemail.js代码语言:javascript复制$(function () {
$("#submit").click(function (event) {
event.preventDefault();
var emailE = $("input[name='email']");
var captcheE = $("input[name='captcha']");
var email = emailE.val();
var captcha = captcheE.val();
zlajax.post({
'url': '/cms/resetemail/',
'data': {'email': email, 'captcha': captcha},
'success': function (data) {
if (data['code'] == 200) {
emailE.val("");
captcheE.val("");
zlalert.alertSuccessToast('恭喜!邮箱修改成功');
} else {
zlalert.alertInfo(data['message']);
}
},
'fail': function (error) {
zlalert.alertNetworkError();
}
});
});
});(5)cms/views.py代码语言:javascript复制class ResetEmail(views.MethodView):
def get(self):
return render_template('cms/cms_resetemail.html')
def post(self):
form = ResetEmailForm(request.form)
if form.validate():
email = form.email.data
g.cms_user.email = email
db.session.commit()
return restful.success()
else:
return restful.params_error(form.get_error())现在就可以修改邮箱了。
【犀牛鸟·视野】持续关注社会媒体处理,腾讯连年参加SMP大会
2018年8月2-4日,全国社会媒体处理大会(National Conference of Social Media Processing,简称SMP大会)在哈尔滨召开,大会主题聚焦“社会媒体”, 吸引了数百位来自全国各地的学术界及企业界人士参加。腾讯分享实践经验继腾讯AI Lab主任张潼博士去年在SMP大会作主题报告后,今年又有两位腾讯的研发人员在主题论坛分享他们的工作,并与领域同行深入探讨。情感分析是社会媒体处理的一个重要子课题。腾讯AILab自然语言处理中心高级研究员邴立东博士分享的是面向目标的情感分类、评论目标抽取以及多领域情感词表示学习等相应任务的最新研究进展。▲ 腾讯AI Lab邴立东博士在情感分析论坛作报告互联网金融已然成为快捷、有效的大众投资和消费渠道,因此其操作的安全性、可控性、稳定性就显得至关重要。腾讯微信技术架构部数据中心陈培炫高级工程师在智能金融论坛上为大家分享了如何使用社交网络相关技术解决金融风控领域的问题,包括将标签传播、协同分类、NetworkEmbedding(LINE、GCN)等应用到金融风控领域的方法。▲ 腾讯微信技术架构部陈培炫在智能金融论坛作报告积极参与评测比赛SMP大会多年来一直坚持组织技术评测比赛,今年有用户画像、中文人机对话和文本溯源三个技术评测比赛,吸引了270支队伍(806位选手)参加。腾讯社交与效果广告部参赛队在竞争最激烈的用户画像技术评测中获得第二名,并现场分享了参赛过程中使用的算法及实验成果。▲ 刘立群代表腾讯社交与效果广告部团队分享实验成果 全国社会媒体处理大会创办于2012年,每年举办一次,现已成为社会媒体处理的重要学术活动。旨在构建社会媒体处理领域的产学研生态圈,成为中国乃至世界社会媒体处理的风向标。SMP2018由中国中文信息学会社会媒体处理专委会主办,哈尔滨工业大学社会计算与信息检索研究中心承办。大会专注于以社会媒体处理为主题的科学研究与工程开发,为传播社会媒体处理最新的学术研究与技术成果提供广泛的交流平台。大会主题聚焦“社会媒体”,如:中文信息处理(自然语言处理、信息检索)、SMP相关计算技术(多媒体、网络分析)、计算社会科学(社会学、传播学)、SMP产业应用(舆情分析)等。
BBS论坛(一)
1.1.项目结构搭建(1)创建flask项目Perfect_bbs,然后搭建项目结构如下:(2)构建蓝图cms/views.py代码语言:javascript复制# cmd/views.py
from flask import Blueprint
bp = Blueprint("cms",__name__,url_prefix='/cms')
@bp.route('/')
def index():
return 'cms index'cms/init.py代码语言:javascript复制from .views import bpcommon/views.py代码语言:javascript复制# common/views.py
from flask import Blueprint
bp = Blueprint("common",__name__,url_prefix='/common')
@bp.route('/')
def index():
return 'common index'common/init.py代码语言:javascript复制from .views import bpfront/views.py代码语言:javascript复制# front/views.py
from flask import Blueprint
bp = Blueprint("front",__name__)
@bp.route('/')
def index():
return 'front index'front/init.py代码语言:javascript复制from .views import bpconfig.py代码语言:javascript复制DEBUG = TruePerfect_bbs.py代码语言:javascript复制# Perfect_bbs.py
from flask import Flask
from apps.cms import bp as cms_bp
from apps.front import bp as front_bp
from apps.common import bp as common_bp
import config
app = Flask(__name__)
app.config.from_object(config)
#注册蓝图
app.register_blueprint(cms_bp)
app.register_blueprint(front_bp)
app.register_blueprint(common_bp)
if __name__ == '__main__':
app.run()运行项目,浏览器访问代码语言:javascript复制http://127.0.0.1:5000
http://127.0.0.1:5000/cms/
http://127.0.0.1:5000/common/1.2.cms用户模型定义建立CMS模型(1)config.py代码语言:javascript复制# config.py
__author__ = 'derek'
DEBUG = True
DB_URI = "mysql+pymysql://root:[email protected]:3306/bbs?charset=utf8"
SQLALCHEMY_DATABASE_URI = DB_URI
SQLALCHEMY_TRACK_MODIFICATIONS =False(2)exts.py代码语言:javascript复制# exts.py
__author__ = 'derek'
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()(3)cms/models.py代码语言:javascript复制# cms/models.py
__author__ = 'derek'
from exts import db
from datetime import datetime
class CMSUser(db.Model):
__tablename__='cms_user'
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
username = db.Column(db.String(50),nullable=False) #不能为空
password = db.Column(db.String(100),nullable=False)
email = db.Column(db.String(50),nullable=False,unique=True) #不能重复
join_time = db.Column(db.DateTime,default=datetime.now)(4)manage.py代码语言:javascript复制# manage.py
__author__ = 'derek'
from flask_script import Manager
from flask_migrate import Migrate,MigrateCommand
from Perfect_bbs import app
from exts import db
from apps.cms import models as cms_models
manager = Manager(app)
Migrate(app,db) #绑定app跟db
manager.add_command('db',MigrateCommand)
if __name__ == '__main__':
manager.run()(5)进cmd终端运行命令,生成到数据库代码语言:javascript复制python manage.py db init # 初始化
python manage.py db migrate #创建迁移脚本
python manage.py db upgrade #生成到数据库进数据库查看项目下面也会多一个migrations目录添加CMS用户(1)Perfect_bbs.py代码语言:javascript复制# Perfect_bbs.py
__author__ = 'derek'
from flask import Flask
from apps.cms import bp as cms_bp
from apps.front import bp as front_bp
from apps.common import bp as common_bp
import config
from exts import db
def create_app():
app = Flask(__name__)
app.config.from_object(config)
app.register_blueprint(cms_bp)
app.register_blueprint(front_bp)
app.register_blueprint(common_bp)
db.init_app(app)
return app
if __name__ == '__main__':
app = create_app()
app.run()(2)manage.py代码语言:javascript复制# manage.py
__author__ = 'derek'
from flask_script import Manager
from flask_migrate import Migrate,MigrateCommand
from Perfect_bbs import create_app
from exts import db
from apps.cms import models as cms_models
CMSUser = cms_models.CMSUser
app = create_app()
manager = Manager(app)
Migrate(app,db) #绑定app跟db
manager.add_command('db',MigrateCommand)
@manager.option('-u','--username',dest='username')
@manager.option('-p','--password',dest='password')
@manager.option('-e','--email',dest='email')
def create_cms_user(username,password,email):
user = CMSUser(username=username,password=password,email=email)
db.session.add(user)
db.session.commit()
print('cms用户添加成功')
if __name__ == '__main__':
manager.run()(3)cmd终端添加用户代码语言:javascript复制python manage.py create_cms_user -u derek -p 123456 -e [email protected]进数据库查看是否添加成功发现密码是明文保存的,显然不行密码加密(1)cms/models.py对外是‘passwor‘’显示,对内是”_password”代码语言:javascript复制# cms/models.py
__author__ = 'derek'
from exts import db
from datetime import datetime
from werkzeug.security import generate_password_hash,check_password_hash
class CMSUser(db.Model):
__tablename__='cms_user'
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
username = db.Column(db.String(50),nullable=False) #不能为空
_password = db.Column(db.String(100),nullable=False)
email = db.Column(db.String(50),nullable=False,unique=True) #不能重复
join_time = db.Column(db.DateTime,default=datetime.now)
def __init__(self,username,password,email):
self.username = username
self.password = password
self.email = email
@property
def password(self):
return self._password
@password.setter
def password(self,raw_password):
self._password = generate_password_hash(raw_password)
def check_password(self,raw_password):
result = check_password_hash(self.password,raw_password)
return result(2)cmd终端重新添加用户更改了字段之后要migrate和upgrade一下代码语言:javascript复制python manage.py db migrate #创建迁移脚本
python manage.py db upgrade #生成到数据库添加用户代码语言:javascript复制python manage.py create_cms_user -u derek -p 123456 -e [email protected]可以看到现在密码是加密保存的了
BBS论坛(十六)
16.登录功能完成(1)front/forms.py代码语言:javascript复制class SigninForm(BaseForm):
telephone = StringField(validators=[Regexp(r'1[3578]\d{9}', message='请输入正确格式的手机号码')])
password = StringField(validators=[Regexp(r'[0-9a-zA-Z_\.]{6,15}', message='请输入正确格式的密码')])
remember=StringField()(2)config.py代码语言:javascript复制FRONT_USER_ID = 'FFFF'(3)front/views.py代码语言:javascript复制class SigninView(views.MethodView):
def get(self):
return_to = request.referrer
if return_to and return_to != request.url and return_to != url_for('front.signup') and safeutils.is_safe_url(
return_to):
return render_template('front/signin.html', return_to=return_to)
else:
return render_template('front/signin.html')
def post(self):
form = SigninForm(request.form)
if form.validate():
telephone = form.telephone.data
password = form.password.data
remember = form.remember.data
user = FrontUser.query.filter_by(telephone=telephone).first()
if user and user.check_password(password):
session[config.FRONT_USER_ID] = user.id
if remember:
session.permanent = True
return restful.success()
else:
return restful.params_error(message='手机号或密码错误')
else:
return restful.params_error(message=form.get_error())(4)front_signin.js代码语言:javascript复制/**
* Created by Administrator on 2018/6/9.
*/
$(function(){
$('#submit-btn').on('click',function(event){
event.preventDefault();
var telephone_input=$('input[name=telephone]');
var password_input=$('input[name=password]');
var remember_input=$('input[name=remember]');
var telephone=telephone_input.val();
var password=password_input.val();
var remember=remember_input.checked?1:0;
zlajax.post({
'url':'/signin/',
'data':{
'telephone':telephone,
'password':password,
'remember':remember
},
'success':function(data){
if(data['code']==200){
var return_to=$('#return-to-span').text();
if(return_to){
window.location=return_to;
}else{
window.location='/'
}
}else{
zlalert.alertInfo(data['message']);
}
}
});
});
});(5)signin.html代码语言:javascript复制 <script src="{{ static('front/js/front_signin.js') }}"></script>
BBS论坛(十四)
14.1注册完成跳到上一个页面(1)front/form.py代码语言:javascript复制# front/forms.py
__author__ = 'derek'
from ..forms import BaseForm
from wtforms import StringField
from wtforms.validators import Regexp,ValidationError,EqualTo
from utils import zlcache
class SignupForm(BaseForm):
telephone=StringField(validators=[Regexp(r'1[3578]\d{9}',message='请输入正确格式的手机号码')])
sms_captcha=StringField(validators=[Regexp(r'\w{4}',message='请输入四位短信验证码')])
username=StringField(validators=[Regexp(r'.{3,15}',message='用户名长度在3-15位之间')])
password=StringField(validators=[Regexp(r'[0-9a-zA-Z_\.]{6,15}',message='请输入正确格式的密码')])
password2=StringField(validators=[EqualTo('password',message='两次输入的密码不一致')])
graph_captcha=StringField(validators=[Regexp(r'\w{4}',message='图形验证码不正确')])
def validate_sms_captcha(self,field):
# 必须传入的参数self,field
# 使用fields.data和使用self.sms_captcha.data是一样的
sms_captcha=field.data
telephone=self.telephone.data
if sms_captcha != '1111':
sms_captcha_mem=zlcache.get(telephone)
if not sms_captcha_mem or sms_captcha_mem.lower() != sms_captcha.lower():
raise ValidationError(message='短信验证码错误')
def validate_graph_captcha(self,field):
graph_captcha=field.data
if graph_captcha != '1111':
graph_captcha_mem=zlcache.get(graph_captcha.lower())
if not graph_captcha_mem:
raise ValidationError(message='图形验证码错误')(2)utils/safeutils.py代码语言:javascript复制from urllib.parse import urlparse,urljoin
from flask import request
def is_safe_url(target):
ref_url = urlparse(request.host_url)
test_url = urlparse(urljoin(request.host_url, target))
return test_url.scheme in ('http', 'https') and \
ref_url.netloc == test_url.netloc(3)front/views.py代码语言:javascript复制class SignupView(views.MethodView):
def get(self):
return_to = request.referrer
if return_to and return_to != request.url and safeutils.is_safe_url(return_to):
return render_template('front/signup.html', return_to=return_to)
else:
return render_template('front/signup.html')
def post(self):
form = SignupForm(request.form)
if form.validate():
telephone = form.telephone.data
username = form.username.data
password = form.password.data
user = FrontUser(telephone=telephone, username=username, password=password)
db.session.add(user)
db.session.commit()
return restful.success()
else:
print(form.get_error())
return restful.params_error(message=form.get_error())(4)front/signup.html代码语言:javascript复制<div class="form-group">
<span style="display: none" id="return-to-span">{{ return_to }}</span>
<button id="submit-btn" class="btn btn-warning btn-block">立即注册</button>
</div>(6)front/signup.js代码语言:javascript复制$(function () {
$('#submit-btn').on('click', function () {
var telephone_input = $('input[name=telephone]');
var sms_captcha_input = $('input[name=sms_captcha]');
var username_input = $('input[name=username]');
var password_input = $('input[name=password1]');
var password2_input = $('input[name=password2]');
var graph_captcha_input = $('input[name=graph_captcha]');
var telephone = telephone_input.val();
var sms_captcha = sms_captcha_input.val();
var username = username_input.val();
var password = password_input.val();
var password2 = password2_input.val();
var graph_captcha = graph_captcha_input.val();
zlajax.post({
'url': '/signup/',
'data': {
'telephone': telephone,
'sms_captcha': sms_captcha,
'username': username,
'password': password,
'password2': password2,
'graph_captcha': graph_captcha
},
'success': function (data) {
if (data['code'] == 200) {
var return_to = $('#return-to-span').text();
if (return_to) {
window.location = return_to
} else {
window.location = '/'
}
} else {
zlalert.alertInfoToast(data['message']);
}
},
'fail': function () {
zlalert.alertNetworkError();
}
});
});
});
DeveMobileEaseMobile 主题双双更新1.1,增加离线存储,社交媒体关注等功能
发布约一周,DeveMobile 、EaseMobile 主题迎来更新1.1 版本更新。1.1 版本为主题增加了HTML5 的离线存储(脱机API)功能及国内常见社交媒体关注功能,并修复若干bug。已购用户请待推送或通知。主题更新内容:0、【EaseMobile】修复EaseMobile 主题与微信机器人插件的冲突问题;评:上一版本在与 我爱水煮鱼 的微信机器人高级插件共同启用时候会有冲突导致主题不能正常运行,本次更新修复这个问题了。请EaseMobile 主题与微信机器人插件的重叠用户尽快更新。1、【DeveMobile/EaseMobile】增加HTML5 的离线存储功能;评:HTML5 的离线存储功能其实就是让你在脱机的时候仍然可以运行网页,当然前提是网页在线的时候已经被访问过了;如果作为Web APP,这个功能非常人性化;当然,因为涉及到兼容性的问题,默认关闭(可在主题设置开启)。2、【DeveMobile/EaseMobile】社交媒体关注组件;评:在侧边栏导航上部会显示出这些社交媒体的logo(暂时有新浪微博、腾讯微博、微信、人人、豆瓣),如果访客点击就会去相应的账户页面。你所要做的是在主题设置那里添加你的社交媒体账号地址。默认也是关闭(可在主题设置开启)。3、【DeveMobile】导航栏上针对交互上做了一些修改,提高用户体验;评:具体而言是如果子菜单过长会自动显示滚动条并上下拖动;其他若干内容。4、【DeveMobile】评论处时间改为 “xxx前”的形式;评:据说这个比较好看。 5、【DeveMobile 】优化在微信内置浏览器的的样式显示;评:微信内置的浏览器不是一般地渣,目前仍然有一些微信内置浏览器显示的bug 还没有修复。6、【DeveMobile/EaseMobile】优化在ipad 等平板设备上的样式显示;评:在平板上空间更大,所以一些空白处稍微增大了。7、【DeveMobile/EaseMobile】其他或大或小的bugs 修复、细节改进。关于主题降价的决定两款移动主题本来说明天后就升价为119 人民币的,不过考虑到可能因为价格定得太高没有卖出几份 o(╯□╰)o ,加上目前主题仍然处于不完善的阶段(功能上还是较少),所以决定暂不升价了,暂时维持109 的售价——所谓的“主题降价”就是如此。以后等完善了再升价也不迟。接下来主题更新是打算区域差异化UI,毕竟现在两款主题的UI 上还是挺接近的,功能上的差异已经有了,但界面设计上Jeff 也打算差异化——不然很多人都以为两款主题只是换了颜色而已。但,一切还要慢慢来。
用JAVA的DEA算法衡量社交媒体页面的流行度
Measuring the Social Media Popularity of Pages with DEA in JAVA原文作者:Vasilis Vryniotis原文地址:http://blog.datumbox.com/measuring-the-social-media-popularity-of-pages-with-dea-in-java/译者微博:@从流域到海域译者博客:blog.csdn.net/solo95用JAVA的DEA算法衡量社交媒体页面的流行度在前面的文章中,我们讨论了数据包络分析(Data Envelopment Analysis)技术,我们已经看到它如何被用作一个有效的非参数排序算法。在这篇博文中,我们将开发出一个JAVA数据包络分析的实例,我们将用它来评估网络上的网页和文章的社交媒体流行度。该代码是开源的(在GPL v3 license下),您可以从Github免费下载。更新:Datumbox机器学习框架现在是开源的,可以免费下载。查看包com.datumbox.framework.algorithms.dea以查看Java中Data Envelopment Analysis的实现。数据包络分析在JAVA中的实现代码是用JAVA编写的,可以直接从Github下载。它是根据GPLv3许可的,所以可以随意使用它,修改它,或者再分发。该代码实现了数据包络分析(Data Envelopment Analysis)算法,使用lp_solve库来解决线性规划问题,并使用Web搜索引擎优化分析(Web SEO Analytics )索引提取的数据,以构建基于Facebook,Google Plus和推特上分享的一个混合的社交媒体页面流行度矩阵。在前面的文章中介绍了算法的所有理论部分,在源代码中可以找到关于其实现的详细的javadoc注释。(原博文之后数据包络分析(Data Envelopment Analysis)算法及其实现全部简称了DEA,请读者注意,译者注。)下面我们提供一个关于其架构实现的高级别描述:1. lp_solve 5.5 library为了解决各种线性规划问题,我们使用一个名为lp\_solve的开源库。某些特定的lib是用ANSI C编写的,并使用JAVA包装来调用库方法。因此,在运行代码之前,您必须在您的系统上安装lp_solve。该库的二进制文件在[Linux和Windows都可以使用,您可以在lp_solve文档中阅读更多有关安装的信息。在尝试运行JAVA代码之前,请确保您的系统上安装了(相关的)特定库。有关安装和配置库的任何问题,请参阅lp_solve文档。2.DataEnvelopmentAnalysis Class这是DEA算法的主要实现类。它实现了一个名为estimateEfficiency()的公共方法,它获取记录的Map并返回它们的DEA得分。3. DeaRecord ObjectDeaRecord是一个特殊的对象,用于存储我们记录的数据。由于DEA需要分离输入和输出,因此DeaRecord对象将以DEA可以处理的方式分别存储我们的数据。4. SocialMediaPopularity ClassSocialMediaPopularity是一个应用程序,它使用DEA来评估社交媒体网络上Facebook的like,Google的 +1和twitter的Tweets的网页流行度。它实现了两个受保护的方法:calculatePopularity()和estimatePercentiles()以及两个公共方法loadFile()和getPopularity()。calculatePopularity()使用DEA实现根据社交媒体计数来估计页面的得分数。estimatedPercentiles()方法获取DEA分数并将其转换为百分位数。总的来说,百分比比DEA分数更容易解释; 因此当我们说一个网页的流行分数是70%时,这意味着该网页比70%的其他网页更受欢迎。为了能够估计一个特定页面的流行度,我们必须有一个包含其他页面的社交媒体数据的数据集。这是有原因的,因为需要预测哪个网页是受欢迎的,哪些不是,您必须能够将其与网络上的其他页面进行比较。为此,我们使用来自以txt格式提供的Web SEO分析索引的小型的匿名样本。您可以通过从网页上的更多页面提取社交媒体计数来构建自己的数据库。(社交媒体计数,比如点赞数、转发数、评论数)loadFile()方法用于加载DEA的上述统计信息,getPopularity()方法是一种易于使用的方法,可以获取Facebook的like,Google的+1和一个页面的Tweets数量,并以此评估其在社交媒体上的流行度。如何使用数据包络分析的JAVA实现在DataEnvelopmentAnalysisExample类中,我提供了2个不同的关于如何使用代码的例子。第一个例子直接使用DEA方法来根据它们的输出(ISSUES,RECEIPTS,REQS)和输入(STOCK,WAGES)来评估组织单位的效率。这个例子来自DEAzone.com的一篇文章。代码语言:txt复制Map<String, DeaRecord> records = new LinkedHashMap<>();
records.put("Depot1", new DeaRecord(new double[]{40.0,55.0,30.0}, new double[]{3.0,5.0}));
//...adding more records here...
DataEnvelopmentAnalysis dea = new DataEnvelopmentAnalysis();
Map<String, Double> results = dea.estimateEfficiency(records);
System.out.println((new TreeMap<>(results)).toString());第二个示例使用我们的社交媒体流行度应用程序,通过使用来自社交媒体的数据来评估页面的流行度,例如Facebook的like,Google的+1和Tweets。所有的社交媒体计数都被标记为输出,我们传递给DEA一个空的输入向量。代码语言:txt复制SocialMediaPopularity rank = new SocialMediaPopularity();
rank.loadFile(DataEnvelopmentAnalysisExample.class.getResource("/datasets/socialcounts.txt"));
Double popularity = rank.getPopularity(135, 337, 9079); //Facebook likes, Google +1s, Tweets
System.out.println("Page Social Media Popularity: "+popularity.toString());必要的扩展(上面)所提供的代码只是DEA如何被用作排名算法的一个例子。为了改进其实现,需要进行下面的扩展:1.加速(算法的)实现特定的DEA算法实现会评估数据库中所有记录的DEA得分。由于我们需要解决如同数据库中记录数量那样多的线性规划问题,这使得实现变得缓慢。如果我们不需要计算所有记录的分数,那么我们可以显著地加快执行速度。因此,该算法的小扩展可以使我们更好地控制哪些记录应该被解决掉,哪些只能被用作约束。2.扩大社交媒体统计数据库(这篇文章所)提供的社交媒体统计数据库由来自Web SEO Analytics索引的1111个样本组成。为了能够估计更准确的流行(度)分数,需要更大的样本。您可以通过统计来自网络上更多页面的社交媒体计数来创建自己的数据库。3.添加更多的社交媒体网络该实现使用Facebook的喜欢,Google的+1和推文的数量来评估文章的受欢迎程度。不过,来自其他社交媒体网络的指标可以很容易地被考虑在内。您只需要从您感兴趣的网络中构建一个社交媒体数据库,然后扩展SocialMediaPopularity类来处理它们。关于实施的最终意见为了能够扩展(算法的)实现,您必须对Data Envelopment Analysis的工作原理有一个很好的理解。这在前面的文章中已经介绍过了,所以在继续进行任何更改之前,请确保您阅读了之前的教程。此外,为了使用JAVA代码,您必须在您的系统中安装lp\_solve库(参见上文)。如果你在一个有趣的项目中使用这个实现,那么就给我们一条线索,我们将在我们的博客上展示你的项目。另外,如果你喜欢这篇文章,请花点时间在Twitter或Facebook分享。
论坛报名 | DataFunCon:AI 平台框架论坛
导读DataFunCon是由DataFun主办的线上技术大会,由20余位知名专家学者出品,设置了18场专题分享,有超过80位一线资深技术专家参与分享,汇集了2020大数据、AI领域最新技术实践。本次大会将于7月25-26日,9:30-18:00在线上举行。7月26日,9:00-12:20,由腾讯大数据智能学习团队负责人陶阳宇先生担任出品人的DataFunCon:AI 平台/框架论坛将准时开启,感兴趣的小伙伴和小编一起来了解下吧:
详细介绍:
出品人:陶阳宇 博士腾讯大数据 | 智能学习团队负责人陶阳宇,腾讯专家工程师,目前担任腾讯大数据智能学习团队负责人,支持腾讯广告推荐、金融支付、社交网络等业务场景的算法模型优化、训练与推理服务。他拥有10余年机器学习、大数据、分布式系统领域从业经验,2009年获中国科技大学电子科技专业博士学位。陶阳宇的主要研究方向包括分布式机器学习系统、广告推荐算法、大数据平台等,曾带领团队获得2015年世界排序大赛冠军及2017年中国电子学会科技进步奖。韩堃 博士滴滴 |AI Labs Researcher
分享主题:DELTA 基于深度学习的语言技术平台内容摘要:近年来,随着深度学习的高速发展,语音和自然语言处理有了越来越多的应用,而这些应用都离不开一套优秀的模型训练和部署框架。为此,我们开发了一个基于深度学习的语言技术平台DELTA,它主要基于TensorFlow构建,能同时支持NLP(自然语言处理)和语音任务及数值型特征的训练。整合了包括文本分类、命名实体识别、自然语言推理、问答、序列到序列文本生成、语音识别、说话人验证、语音情感识别等重要算法模型,形成一致的代码组织架构,整体包装统一接口。本次演讲会着重介绍DELTA的基本架构和使用,并也会针对滴滴在用DELTA在语音交互领域所做的工作做一个整体的梳理。听众收益:了解DELTA的架构和使用,并且了解基于DELTA的实际应用方法。新技术/实用技术点:DETLA简介,架构,设计思路,包括多种深度学习模型的训练和使用,文本分类,命名实体识别,端到端文本生成,语音识别,语音情感识别等。嘉宾简介:韩堃毕业于The Ohio State University,2013年在微软研究院实习,主要研究方向为语音处理和机器学习。韩堃于2014年获博士学位,并加入Facebook从事语音,自然语言处理,机器学习等工作。2018年加入滴滴AI Labs,负责语音交互,对话理解等方向的研究与产品。王辉华为 |开源工程师分享主题:MindSpore简介以及与TVM的联动内容摘要:MindSpore是一套最佳匹配昇腾AI处理器算力,可用于端边云全场景的开源深度学习框架。本次分享我将为您介绍MindSpore的大体框架,及其在WASM领域与TVM项目的联动方案,最后我准备了一个Demo用于展示该方案的成果。听众收益:通过本次分享,您将会对MindSpore框架的介绍和使用有一定的了解;同时会熟悉TVM编译栈和Runtime的大致流程;最后会学习到如何将WebAssembly技术在AI领域进行落地。新技术/实用技术点:WebAssembly技术:WASM是一种为堆栈式进程虚拟机实现定义的二进制指令格式,目前已成为Web领域的事实标准;WASM Kernel Compiler:利用TVM针对单算子的LLVM编译生成WASM文件,并通过WASM Runtime进行WASM算子的加载;WASM Graph Compiler:利用TVM针对网络整图的LLVM编译生成WASM文件,并通过WASM Runtime进行WASM图的加载。嘉宾简介:王辉是一名来自华为的开源工程师,在过去的四年里专注于新领域(人工智能、芯片、云)和开源技术研究。目前负责新型计算运行时(例如WebAssembly技术)研究和MindSpore AI框架的开源社区运营。在此之前,他作为OpenSDS Hotpot项目的PTL与OpenSDS团队一起工作,同时也是OpenStack、OPNFV和Open Service Broker API等社区的积极贡献者。郭跃超腾讯 |应用研究员分享主题:Angel深度学习在广告推荐训练系统中的实践内容摘要:Angel是腾讯开源的分布式深度学习框架,支持数据并行、模型并行等多种大规模机器学习模型的训练和加速。本次演讲将介绍Angel深度学习在广告推荐中的应用实践,解决广告推荐CV、用户行为等特征模型训练时的多机多卡扩展等加速问题,以及取得的实践成果。听众收益:通过本次分享,您将会对Angel平台,分布式的相关的技术,以及广告推荐模型训练有一定的了解;同时会学习到,一个生产力工具如何进入业务流程中,如何面对实际问题进行反馈调整,并最终产生实际收益的。新技术/实用技术点:分布式模型训练多卡扩展;广告推荐深度特征生产技术等。嘉宾简介:郭跃超毕业于北京大学,主要研究方向是异构加速计算,分布式系统的设计开发和优化,语音/NLP等领域的算法优化等。目前在腾讯主要负责Angel平台的深度学习方面的新技术研究,开发和业务场景的落地应用。吴志华百度 |资深研发工程师分享主题:飞桨框架和分布式训练技术及其应用内容摘要:飞桨是源于产业实践的开源深度学习平台。本次分享主要介绍飞桨的核心框架、基础模型库、工具组件。并针对分布式训练模块展开详细介绍,带大家深入了解飞桨超大规模深度学习模型训练技术,以及在信息流、广告、搜索等业务场景上的应用。新技术/实用技术点:深度学习训练框架分布式训练技术推荐算法及业务应用嘉宾简介:百度飞桨资深研发工程师,主要负责飞桨分布式参数服务器架构、PaddleRec推荐算法库及其在信息流、广告、搜索等业务上的应用。李晓森腾讯 |高级研究员分享主题:Angel图计算技术与实践内容摘要:万物互连构成了复杂的网络世界,同时也积累了丰富的图数据,并蕴藏着极大的价值;本次分享将介绍Angel是如何解决图计算中的三驾马车问题——传统图算法/图表示学习/图神经网络,最终助力内部QQ、支付、音乐、安全等业务提升效果。听众收益:图计算的应用场景,以及基于参数服务器的图计算架构,图计算在腾讯业务中的业务实践。新技术/实用技术点:基于参数服务器的图计算架构,图计算中的常用优化方法。嘉宾简介:李晓森 ( hansenli ),硕士毕业于北京大学,腾讯大数据高级研究员,腾讯图计算开源协同项目Owner PMC,参与Angel图计算项目,专注于图计算在金融支付、安全风控、广告推荐、知识图谱等多个场景的落地。活动报名:识别二维码,免费报名
扫码关注 | 即刻了解腾讯大数据技术动态
微博市值反超Twitter成市值最高社交媒体股 一下科技强力助攻
2016年,新浪微博在短视频、直播、网红等领域持续发力,股价自今年2月以来持续上涨,迈入“百亿美元俱乐部”。就在本周,微博股价一度上涨至53.12美元,市值达113.5亿美元,超过Twitter市值1000万美元,成为全球市值最高的社交媒体。在这次里程碑事件中,旗下拥有秒拍、一直播、小咖秀三款产品的一下科技起到了重要的助推作用。
合作移动视频行业独角兽 微博实现二次崛起摩根士丹利最近发布报告指出,短视频和直播正在推动微博用户增长,从产品形态来看,微博已经变成类似于Twitter+Instagram+YouTube的综合平台,不再是成立之初“Twitter”的模仿者。其中,这个YouTube 的部分就来自移动视频行业独角兽企业一下科技。作为战略合作方,一下科技旗下秒拍、小咖秀、一直播三款产品SDK内嵌到微博中,实现数据互通,三者为微博贡献海量PUGC内容。从移动端看,短视频用户的基数已经超过了社交媒体,新浪微博正是瞄准了短视频行业这一巨大红利窗口。作为国内最大的PGC短视频播放平台,秒拍日均上传视频量达150万,成为微博内容重要提供方;小咖秀带动全民秀演技,在最近的模仿傅园慧采访片段和魔性神曲《PPAP》热潮中,吸引了包括贾乃亮、古力娜扎在内的一众明星参与;一直播自今年5月上线后更是为微博带来爆发式增长,特别是国庆期间同微博一起推出的#带着微博去旅行#活动,由于直播这一新形式的加入,活动相关话题阅读量达168亿次,超过去年近3倍,成为现象级标志性事件。一下科技三款产品视频内容输出对微博用户活跃方面带来的提升显而易见,微博用户活跃度连续九个季度保持30%以上的增长,尤其是在一直播上线后,更是迎来阶梯式上涨。反观产品形态较为单一的Twitter,在过去一年内,流失了500万的月活跃用户,用户增长乏力。(微博与Twitter用户增长对比,数据来源Bloomberg)一下科技助力微博深耕短视频内容 发展网红经济在微博的内容生态和商业生态中,网红已经成为平台流量入口和商业变现的重要一环。“集美貌与才华于一身的女子”papi酱、贱贱的以BOBO头形象传授化妆技巧的艾克里里和在小咖秀里狂飙演技的“华妃娘娘”蒋欣等明星达人,提升了微博的热度。尤其是一直播上线后,加入金币打赏模式,网红们商业变现方式增多了、周期变短了,相应的,网红群体数量也随之变多了、积极性也更高了,各行业、领域之间也开始出现了垂直细化的趋势。网红群体的商业前景很大,微博希望通过类似于MCN的模式将其内化吸收,让网红经济不再野蛮生长,而是遵循一定营运规则和商业规则。在这一领域微博同样与一下科技强强联手,打造业内最大的红人平台。去年底,新浪微博还与一下科技共同拿出1亿美元来帮助短视频原创作者,整合上下游商业链条,并在近期推出“秒拍创作者平台”,“秒拍惠”等平台政策,为更多原创作者提供数据、流量、商业收入、视频制作等方面的资源倾斜,让短视频创作者更垂直化、知识化、圈层化发展,成为打造网红的星工场。明星、行业KOL等头部资源对平台流量具有巨大吸力,微博与秒拍、小咖秀、一直播构成的生态联合体拥有明星、网红、KOL资源是任何其他单一平台都无法超越的。在维护好原有红人关系同时,微博和一下科技也在努力培养“新网红”,于10月初联手上线的“微博校园红人季”活动和即将举行的“V影响力峰会”都是在网红领域打造的明星活动。此外,一下科技也将依托“秒拍+小咖秀+一直播”的生态联合体,为微博输送更多红人血液。微博同一下科技的强强联合,整合了时下最具商业价值的移动视频行业和网红经济,两者所承载的庞大流量不仅使微博提升了用户活跃度,最终实现二次崛起,更是为微博带来了更多的移动用户,并反应在商业变现领域,最终使得此次微博市值首超Twitter。
CVPR禁令出台:审稿期间禁止主动在社交媒体宣传论文!LeCun:阻碍科学交流,简直疯了
新智元报道来源:Twitter编辑:David【新智元导读】计算机顶会CVPR颁布「社交媒体」禁令,在论文审稿期间,禁止论文作者以任何形式通过社交媒体对论文进行讨论或自我宣传,但Arxiv不在禁止之列。此令一出,社区炸锅,反对者众。对于计算机科学领域的研究人员来说,每年的顶级学术会议,即「顶会」的分量都是毋庸置疑的。
很多时候,准备向顶会提交论文的作者会通过社交媒体,把自己的论文事先做一波宣传。在促进学术交流的同时,也能让更多人了解自己的成果。不过现在,计算机顶会之一的CVPR宣布,从此刻开始,此路不通了。当地时间10月20日,CVPR通过Twitter发布通知,明确规定:提交CVPR的论文在审稿期间,禁止论文作者以任何形式在社交媒体上进行讨论或自我宣传。通知全文是这样的:CVPR 2021 PAMI-TC 会议此前已经通过动议,论文作者在评议期间不应使用社交媒体传播向 CVPR 提交的论文。在动议中定义了社交媒体的沉默期。社交媒体的沉默期从论文提交截止日期前四周开始,直到论文最终结果通知发送给作者的时间。根据目前的时间表,此静默期从 2021 年 10 月 19 日到 2022 年 3 月 2 日。在此期间,任何由作者主动发起的对论文的社交媒体宣传都被视为违反政策。CVPR认为,此项政策有助于保持双盲评审的公信力。「社交网络」禁令6月即已敲定,但Arxiv例外值得注意的是,这次发布的通知中提到,包含这项政策的动议在「此前」已经通过。实际上,这项动议是今年6月在PAMI-TC会议上由计算机科学家、德国马克斯·普朗克智能系统研究所所长 Michael Black 提出的。这份动议认为,现行政策对于投稿作者在社交媒体宣传自己的论文的行为无法有效制约,而且定义含混,只要作者没有明确说明文章处于会议审稿阶段,就允许在社交媒体上宣传。这种宣传愈演愈烈,无疑会影响双盲评审的信度,影响审稿人对文章质量的判断。同时,在社交媒体上拥有众多追随者的大V们会借此获得更大的舆论优势,降低了大众对评审制度公平性的信任,也会影响科学界内部的互信。不过,这份动议把Arxiv排除在了禁令之外,理由是:首先,arXiv 上的论文不是“已发表”,而是“预发表”。这种公开的发表前流程属于一种可以发现问题的社区评议形式,和正式的同行评议很类似。其次,将论文放在 arXiv 上供专家进行早期分析,与在社交媒体上向广大受众公开宣传有很大不同。会议认为,这一新政策并不会减缓科学进步,而且关注Arxiv的大多是专家,而不是普通大众,这与在社交媒体上宣传论文的受众有很大区别。此动议被高票通过。社区炸锅,反对者众,LeCun直呼「疯了」此通知一出,立即引发网友热烈讨论。有Reddit网友表示,这个政策初衷是好的,社交媒体宣传论文泛滥是该治一治了,但是可能解决不了问题。这确实是不错的一步,但实际实行起来很难,因为操作起来可以绕过「主动宣传」的方法太多了。比如,现在的规定只是禁止作者在社交网络上贴出向CVPR送审的论文链接,但如果作者发在Arxiv上,根本不提在CVPR评议的事儿,那就难办了。还有网友表示,这个政策看起来是促进公平,实际上是进一步加剧了不公平。理由很简单,如果作者是大牛,本身就鼎鼎大名,又背靠知名机构,不需要通过社交媒体宣传,其他途径多的是。但对于一般作者,社交媒体不让用了,那可真的没啥别的招了。这个政策会继续拉大「贫富差距」,大机构通过其他方式获得更多关注,小团队和小实验室可能会越来越不为人所知。此处点名Facebook、DeepMind……还有网友认为,说了半天,Arxiv不禁,光禁止社交媒体,这政策漏洞岂不是更大了吗?干脆论文评议改成「单盲」算了。而研究人员方面,对此次禁令的态度以反对意见居多。比如从事机器人、计算机视觉和农业自动化交叉研究的Amy Tabb,早在今年6月此动议通过时,就列出了一份比较详细的观点,系统阐述了她的反对理由。她的主要理由有三:
这项政策会引发寒蝉效应。实际上,向其他科学家和公众公开谈论自己的工作,无论通过哪种媒介都是同样重要的,既包括社交媒体,也包括Arxiv。
那些不遵守规则、喜欢钻空子的人通过媒体推广会得到更多的好处。只要匿名发表就能逃过规则监管,这份动议的规则漏洞太明显。
这项政策的实际效果与设计初衷不符。最终不会限制大型实验室或有大量粉丝的人,遭殃的反而是小型实验室和不知名的研究人员。她的观点得到了深度学习先驱、图灵奖得主Yann LeCun的支持。LeCun转发了Tabb发表反对意见的推文,认为她的意见是对的。LeCun还表示,CVPR这个政策,限制了科学信息的有效交流和沟通,阻碍了进步,简直是疯了。
不难看出,此次CVPR「禁令」的出台,无论是在动议阶段还是颁布实施,都争议不断。后续实际效果如何,尚待时间检验。
参考链接:
https://amytabb.com/tips/2021/06/15/cvpr-motion-position/https://twitter.com/Michael_J_Black/status/1402262709106884610https://www.reddit.com/r/MachineLearning/comments/qbslai/r_cvpr_expands_social_media_ban/?sort=confidencehttps://twitter.com/CVPR/status/1450641549294018560
在社交媒体上,你和ai的区别是,你有多“懒”?
大数据文摘出品来源:frontiersin编译:Fisher、刘俊寰一说到机器人账号,大多数人脑海里第一反应都是水军、控评,如果在国外竞选期间,这些机器人账号还能在社交媒体上被广泛运用于舆论操作中,想来后怕。但是机器人账号也有积极的一面,不少公司将其运用到新闻聚合、在线零售等领域,也着实为人们制造了不少便利。根据2017年的一项调查,Twitter中的机器人数量达4800万,占比15%。在庞大的虚拟AI用户占比和信息爆炸的夹击下,我们如何分辨一个账号究竟是真实的人类,还是虚拟的AI账号?早在1993年,Peter Steiner在《纽约客》刊登了一幅漫画,“在互联网上,没人知道你是一条狗”,被传诵至今。不过现在,我们或许要改一改,“在互联网上,没人知道你是一个AI”。以“懒”识人!随着话题演进,人类用户原创内容递减最近,《物理学前沿》发表了一项新研究,主要研究的正是人类用户和AI用户之间的区别,他们发现人类用户和AI用户并非无法区分。论文指出,人类用户存在短期行为趋势,但机器人账号不存在这类趋势,也就是说,在互联网上人类有着自己的“专属标签”,这恰是关键所在。论文链接:https://www.frontiersin.org/articles/10.3389/fphy.2020.00125/full?utm_source=fwebutm_medium=nblogutm_campaign=ba-sci-fphy-physics-ai-bots结果显示,随着话题的演进,人类用户参与社交互动的数量会增加,但是并非表示为增加原创内容,增加的只是转发、回复的比例,以及单条推文中提及话题的次数。与此同时,人类用户原创的内容在减少,推文平均长度呈下降趋势。这些趋势的成因被认为是随着事件发展,人类用户对该话题越来越感到疲劳,更不倾向于做出复杂行为。另一个可能的解释是,随着时间的推移,用户接触到更多的帖子,因此增加了他们对内容做出反应和互动的概率。无论是哪种情况,机器人都被证明不受这些因素的影响,没有观察到它们的行为随时间发生变化。也就是说,区分人类用户和AI用户的关键点在于是否能从他们的推文中察觉到“懒”的痕迹。AI:有被摆了一道的感觉。首次研究AI用户的检测问题值得注意的是,这项研究可用于开发更精准的机器人检测策略,该研究将用户在社交媒体会话中的行为用于机器人检测问题,在同类研究中尚属首次。在这项工作中,研究人员使用一个与近期政治事件相关的大型Twitter数据集,研究了人类账号和机器人账号的行为如何随着某个话题的进展而改变。对这些话题演进的整个过程,研究人员计量了多种因素,以捕捉用户的行为特征,包括参与社交互动的倾向和产生的内容量,然后将这些结果在机器人和人类之间进行了比较。对此,研究人员关注的社交媒体行为包括转发数、回复数和推文中提及话题的次数,以及推文本身的长度。也就是说,他们关注的是能够刻画用户参与社交互动的数量和质量。确定研究标准之后,研究人员将结果用于优化机器人检测系统,观察加入这些新特征后是否能提高检测器的性能。他们使用了一系列机器学习技术对两套不同的分类器进行了训练:一套包含这些新特征,另一套不包含以作为基准。研究人员用这些行为特征来优化机器人检测系统,他们发现包含时间动态特征的完整模型在检测准确性上明显优于未考虑这些特征的基准模型。这些结果凸显了在话题进展的过程中,机器人账号和人类用户之间存在可以计量的行为演变上的差异;同时表明这些差异可以用来实现一个机器人检测系统,或者用来改进现有的系统。“值得注意的是,机器人在不断改进,越来越多地模仿人类在社交媒体上的行为。每当我们发现一个我们以为是人类独有的行为特征,比如在一个账号所关注的话题中体现出的思想情绪,我们会发现,新开发的机器人已经可以体现这些特征了。”论文的共同作者、南加州大学信息科学学院计算机科学助理教授兼研究团队负责人Emilio Ferrara博士说。Emilio强调说,“机器人在不断进化——随着人工智能的快步推进,有可能创造出越来越逼真的机器人,可以越来越好地模仿我们在网络平台上讲话和互动的方式。”“我们在不断尝试发现社交媒体上的人类行为所特有的维度,这些发现又能用来开发更精准的工具以检测机器人。“相关报道:https://blog.frontiersin.org/2020/04/22/whos-a-bot-and-whos-not/
「多媒体与XR圆桌论坛」直播预约已开启!
11月30日,腾讯面向产业互联网领域规格最高、规模最大、覆盖最广的年度盛会——腾讯全球数字生态大会将在深圳国际会展中心正式拉开帷幕。本届大会以「数实创新 ,产业共进」为主题,聚焦数实融合,共设置了50余场行业及产品系列专场,为全球客户及用户分享产业互联网最前沿的产品成果和研讨对话!由腾讯多媒体实验室主办的LIKE.TG多媒体技术专场「多媒体与XR圆桌论坛」将在12月1日14:00-16:00举行,请扫码预约直播。多媒体赛道,作为XR落地产业应用的桥头堡领域,吸引的关注超乎想象。全真互联网时代背景下,用户视觉体验的优劣愈发重要。如何基于低码率高画质、超分等视频处理技术带来的画质提升、三维视频带来的深度感知、任意视点视频带来的用户交互、扩展现实与虛拟现实带来的超现实感,成为业界关注的焦点。为此,本专场邀请到 IEEE Fellow、腾讯杰出科学家、腾讯多媒体实验室负责人 刘杉博士,中国工程院院士、广播电视技术专家 丁文华院士,IEEE Fellow、清华大学计算机科学与技术系教授 温江涛博士,全景声科技创始人、董事长 潘兴德博士,腾讯多媒体实验室扩展媒体中心负责人、国际标准专家 许晓中博士,腾讯在线视频BU播放技术中心总监 朱子荣,共同探讨多媒体与XR的技术前沿趋势。聚焦XR国际标准制定、编解码应用、音视频沉浸式体验以及XR未来畅想,分享腾讯多媒体实验室在此领域的技术积累与战略方向,一同发掘在全真时代与智能时代里多媒体与XR技术的无限可能。圆桌主持人
重磅嘉宾