个好消息,(新浪)微博也支持 SVG 了。
一个坏消息,品牌方的内卷新赛道又诞生了。
一个更好也可能更坏的消息,(新浪)微博与微信公众号生态的 SVG 语法框架形式有较大差异。但有个值得一提好消息是,据了解 E2.COOL 黑科技 SVG 编辑器已经开始上架微博 SVG Beta 专用模版。
究竟怎么回事?
先行科普一下。
大家好我是交互设计师计育韬,首先非常感谢微博的这次 40+ 专业用户内测邀约活动。虽然我是其中唯一的技术侧(其他均为平台侧)个体,但无论是产品体验还是技术交流,计老师都已经感受到了微博官方的产品诚意和平等姿态,点赞!未来更多的微博 SVG 产品动态一定要关注微博账号 @头条文章,官方资讯将以此为准喔!
还不了解什么是 SVG?摒弃纯技术性的概念诠释,简单来讲微信公众号图文中具备通过手指点击等行为产生交互响应的画面,如今大多基于 SVG 技术。圈内的 SVG 品牌头号玩家包括 GQ 实验室、宝马中国、喜茶、蒂芙尼、蕉内等,想必对运营人而言都是如雷贯耳般的存在。
如果你想进一步理解它,那么可以阅读我的科普专著《硬核运营:新媒体技术流养成》,在大多数市立和高校图书馆都可以借阅到。
内测体验如何?
开发层面可有差异?
以下是基本的操作指南,请务必收藏好或传阅给具体岗位的运营人员:对于已经获取内测资格的账号而言,只需要在编辑微博头条文章时,点击剪切板功能,再点击「插入 SVG 代码」按钮即可——
就是如此简单,而需要注意的是:
1)头条文章的 SVG 支持按板块编辑,这就意味着文本穿插 SVG 交互的排版制作起来会轻松得多,对比之下微信公众号图文草稿编辑页始终是没有官方 SVG 编辑入口的,一切都需要依赖各类第三方插件进行布局。
2)它的本质是代码的编辑窗口,因此不仅限于插入 <svg></svg> 结构,也可以将譬如横向滑动(CSS)、视差(perspective 裸眼 3D)等布局进来,那么这里就是一个重要的想象力突破口了。
(品牌方如需查看内测案例预览请微信小窗与我联系)
而提到想象力,SVG 发展至今、其有效的信息分层、酷炫的动画特效、丰富的感官体验……让我作为行业的先行者都尤其欣慰。且身为研究型学者,计老师也通过公益普及和培训授课等形式间接孵化了大批青年工作室团队,相信他们很快也会投入微博端 SVG 设计研究,为每一个普通的运营人提前铺平应用道路。
当然请注意,微博 SVG 的编辑区目前是存在字符限制的,对于顶尖开发者来说如果你植入重型交互装置,很可能当前不在微博 SVG 接受范围内,建议控制到 30W 代码字符以下:
但正如开场所言,W3C 联盟提供了 SVG 的全部应用空间,而 APP 则要具体问题具体分析,通过「白名单」这类属性与能力的限制规则,管控 SVG 可能干扰到 APP 生态自身技术架构稳定性的因素。
所以现在,我要谈一谈微博 SVG 交互设计与微信公众号生态的区别,无论你是专业开发者还是内容运营人,都请仔细阅读接下来的说明!
以微信公众号为例,很多行业晚辈可能并不了解,在 2016 年为了和微信团队敲定《微信下 SVG AttributeName 白名单》,我和厦门嘉庚学院的研究人员就通过各种压力测试限制了 1)部分 AttributeName 的属性(在彼时可能导致微信闪退)2)属性引用能力(避免误扰到图文外层 CSS 样式)。且随着行业的发展,白名单中又出现了如对包括 <embed>、<detail> 标签,以及 <width>、<height> 动画重复次数等非常细节化的限制。
因为在任何生态中,都存在看不见的力量随时觊觎平台漏洞之下的财富。「白名单」的本质不是为了制约创作者,而是守住平台的底线,并给予所有参与人公平公正的运行环境。所以作为规则的制定者,总有其苦衷可能无法为后人理解,但在无形中只要维护好了微信的生态安全,其他纷扰就不值一提了。
那么,微博 SVG 生态内包含形同「白名单」的同类规则吗?
我确切地告诉你,这是肯定的。并且,它在未来也一定会不断被迭代更新。目前,微博 SVG 也同样制约 <script> 的应用,Dom 相关事件如 onload、onclick 等。不过对于 <id>,微博 SVG 持开放态度,这就意味着——
微博的 SVG 是相对更「科学」的 SVG,生态内的被动动画代码书写逻辑与微信公众号生态可以截然不同。它更倾向于 H5 的设计思维,易于被运营人理解和学习。与此同时,它的动画丰富性理论上限可能远超微信公众号生态圈,我们的一次简单的点击行为,可以绑定到无限数量目标的不同动画形式。
此外,包括 <use> 等标签的应用已成为可能,开发者通过定义可重复使用的元素的标签,能更高效地在 SVG 内布局它们;滤镜、渐变、蒙版等一大批在矢量设计软件中司空见惯的艺术特性,基于 <id> 或能实现正确表达……
而针对微博 SVG 的规则差异,建议各大主流 SVG 编辑器(秀米、135、E2.COOL)在将来提供对应的专属组件或独立操作专区,虽说有大量既往的 SVG 模板确实能在微博中复用,但创想的远帆已经悄然扬起,更史诗感的交互体验一定会诞生在微博上而不是微信公众号内。
至于当下,微博 SVG 的「白名单」尚未完全敲定,我在也参与协助测试之中。此后等产研侧有了明确的定数,我会第一时间如发布微信 SVG AttributeName 白名单那样与大家分享准确技术信息。也在此告诫,任何尝试以突破或绕过微博 SVG 相关功能限制进行开发的行为,都在技术圈被定位为「对抗式开发」,这无论在哪一个平台内都是不会被允许的。尊重生态,尊重平台,对开发环境抱有基本的感恩之心,这是每一个开发者应当秉持的良好职业道德。
查看更多实例
聊聊创作的想象空间
微博官方最早是于今年 3 月由内部人员启动生产环境的产品测试,很高兴地看到当时的一些实例就已经在应用著名的 E2.COOL 黑科技 SVG 编辑器。那么再结合一些圈内最新的测试,接下来计老师带同学们了解更多具体案例及其技术意义。
一、循序渐进,从简单特效开始实践
最具代表性的微信公众号 SVG 效果是什么?如果只能选一个的话,计老师认为「点击-伸长」型组件非其莫属。对于大多数运营人来讲,它的直观属性就是使得图文画面向下延展,扩大可视范围并展示出更多内容。对开发者而言,它经历了一代定宽伸长(@GL 意符互动发明),二代分层定宽伸长(@Apple 发明),三代 <width> 式分层适配伸长(@小杨 交互实验室发明)和准 3.5 代类积分思维收缩/伸长(@科蚪发明),那么它可以被应用在微博 SVG 吗?怎么用?
(品牌方如需查看内测案例预览请微信小窗与我联系)
首先,由于方才提到我们尚未敲定最终的微博 SVG 白名单规则,因此初步上手先选择简单形态的伸长更为稳妥。如这个实例就是 3 月份时候,博主基于 E2.COOL 黑科技 SVG 编辑器最基本的「点击-伸长」、「点击渐现」组件进行的一次案例复用实验。
考虑到微博 SVG 生态正处于起步阶段,对于并不真正熟悉 SVG 代码运行逻辑的运营人来说,当下如果能获得内测资格,那么应用好这类基本动画效果足矣。至于具体的模版操作流程,还是建议关注编辑器侧的资讯动态。
在完成「点击-伸长」案例基础上,或许你就能再逐步通过自由拼装,去完成「上色伸长」这样更多的进阶伸长动画效果。
(品牌方如需查看内测案例预览请微信小窗与我联系)
如上微博 SVG 实例的排版方法为:
对于头部品牌,如果希望尽快获得微博 SVG 能力,可以与我们 JZ Creative Studio 取得联系,目前计老师也正在安排部分我们的长期研究合作品牌开启相关功能并正式投入内容制作。且出于科研目的,我们依然会免费定制开发超越微信公众号生态可能性的更高级 SVG 交互设计。
二、转变思维,探索更丰富的动画能力
前面已经提到,微博 SVG 的理论效果上限目前是明确高于微信公众号生态的,下面这个我布局的实例则为了表现 <id> 能力带来的新特性。
(品牌方如需查看内测案例预览请微信小窗与我联系)
通过「长按」画面,魔方中的三个立方体会朝三个方向各自运行,「松开」画面后它们又回逐步回到原位。且画面中的实体素材只有一个立方体,魔方的构成通过同一元素堆叠而成。讲到这里,相信专业开发者们已经欣喜万分。具体的技术细节在此我就不展开了,有需要的读者请移步今天发布的次条图文。
你也可以前往 E2.COOL 黑科技 SVG 编辑器通过微博 SVG Beta 专用模版来理解这种关键能力的多样化应用效果,像其中的「E2爆炸图」模版就是非常典型的交互效果。
如何申请内测?
既往的长期深度合作伙伴可以直接咨询 JZ(管理员微信 Zhuoya_Work),我们会视品牌方微博和微信公众号的实际情况,决定是否交由微博官方开启对应功能。
而对于需要自行申请内测则可以向本公众号回复「微博SVG内测」获取申请链接排队参与。
如果你有任何建议,或在加入内测后遇到任何困难,欢迎通过不同渠道与我们联系,我们将尽快汇总重要的用户反馈,交由微博官方进行研究和回复。
更多入门指南、实例分析、模版推荐请移步本期发布的次条链接点击阅读。我们也会尽快组织包括公开直播课、教学录播课等形式的科普工作,同时也将在知识星球开始更新相关研究的最新成果:
021年你需要知道的HTML标签和属性
Web开发人员都在广泛的使用HTML。无论你使用什么框架或者选择哪个后端语言,框架在变,但是HTML始终如一。尽管被广泛使用,但还是有一些标签或者属性是大部分开发者不熟知的。虽然现在有很多的模版引擎供我们使用,但是乐字节教育的老师和我们说还是需要尽可能的熟练掌握HTML内容,就像CSS一样。
在我看来,最好尽可能使用HTML特性来实现我们的功能,而不是使用JavaScript实现相同的功能,尽管我承认编写HTML可能会是重复的和无聊的。
尽管许多开发人员每天都在使用HTML,但他们并没有尝试改进自己的项目,也没有真正利用HTML的一些鲜为人知的特性。
下面这5个通过HTML标签/属性实现的功能我觉得需要了解一下:
图片懒加载
图片懒加载可以帮助提升网站的性能和响应能力。图片懒加载可以避免立即加载那些不在屏幕中立即显示的图片素材,当用户滚动临近图片时再去开始加载。
换言之,当用户滚动到图片出现时再进行加载,否则不加载。这就降低了屏幕内容展示过程中的图片素材的请求数量,提升了站点性能。
往往我们都是通过javascript来实现的,通过监听页面滚动事件来确定加载对应的资源。但是,在不完全考虑兼容性的场景下,我们其实可以直接通过HTML来直接实现。
注:本篇的提到的标签和属性的兼容性需要大家根据实际场景来选取是否使用
可以通过为图片文件添加loading="lazy"的属性来实现:
输入提示
当用户在进行输入搜索功能时,如果能够给出有效的提示,这会大大提升用户体验。输入建议和自动完成功能现在到处可见,我们可以使用Javascript添加输入建议,方法是在输入框上设置事件侦听器,然后将搜索到的关键词与预定义的建议相匹配。
其实,HTML也是能够让我们来实现预定义输入建议功能的,通过<datalist>标签来实现。需要注意的是,使用时这个标签的id属性需要和input元素的list属性一致。
Picture标签
你是否遇到过在不同场景或者不同尺寸的设备上面的时候,图片展示适配问题呢?我想大家都遇到过。
针对只有一个尺寸的图片素材的时候,我们往往可以通过CSS的object-fit属性来进行裁切适配。但是有些时候需要针对不同的分辨率来显示不同尺寸的图片的场景的时候,我们是否可以直接通过HTML来实现呢?
HTML提供了<picture>标签,允许我们来添加多张图片资源,并且根据不同的分辨率需求来展示不同的图片。
我们可以定义不同区间的最小分辨率来确定图片素材,这个标签的使用有些类似<audio>和<video>标签。
Base URL
当我们的页面有大量的锚点跳转或者静态资源加载时,并且这些跳转或者资源都在统一的域名的场景时,我们可以通过<base>标签来简化这个处理。
例如,我们有一个列表需要跳转到微博的不同大V的主页,我们就可以通过设置来简化跳转路径
<base>标记必须具有href和target属性。
页面重定向(刷新)
当我们希望实现一段时间后或者是立即重定向到另一个页面的功能时,我们可以直接通过HTML来实现。
我们经常会遇到有些站点会有这样一个功能,“5s后页面将跳转”。这个交互可以嵌入到HTML中,直接通过<meta>标签,设置http-equiv="refresh"来实现
这里content属性指定了重定向发生的秒数。值得一提的是,尽管谷歌声称这种形式的重定向和其他的重定向方式一样可用,但是使用这种类型的重定向其实并不是那么的优雅,往往会显得很突兀。
因此,最好在某些特殊的情况下使用它,比如在长时间用户不活动之后再重定向到目标页面。
后记
HTML和CSS是非常强大的,哪怕我们仅仅使用这两种技术也能创建出一些奇妙的网站。虽然它们的使用量很大很普遍,还是有很多的开发者并没有真正的深入了解他们,还有很多的内容需要我们深入的去学习和理解,实践,有很多的技巧等待着我们去发现。
文章转载至乐字节
最后给大家推荐几个b站超详细的Java自学课:
Servlet入门教程BV1D5411373E
Vue、Vuejs教程,BV19V41177od
SpringBoot+Vue项目实战BV1o64y117qQ
lask是Django之外用Python实现的另一优秀Web框架
今天用它
Flask以自由、灵活著称。在开发一些小应用的时候,使用Django会有“杀鸡用牛刀”的赶脚,而使用Flask就非常合适。本文将使用Flask开发一个微博用户画像的生成器,最后效果如下:
开发步骤如下:
抓取微博用户数据;
分析数据,生成用户画像;
网站实现,美化界面。
一、微博抓取
这里使用移动端的微博(m.weibo.cn),以为例。本教程使用chrome浏览器进行调试。
在“发现”中搜索“古力娜扎”,点击进入她的主页;
开始分析请求报文, 右击打开调试窗口,选择调试窗口的"网络(network)"标签;
选择"Preserve Log",刷新页面;
分析各条请求过程可以发现博文的数据是从https://m.weibo.cn/api/container/getIndex?XXX 类似的地址中得到的。其主要参数为type(固定值)、value(博主ID)、containerid(标识,请求中返回)、page(页码)
下面开始实现爬取博文的代码。
# 导入相关库
import requests
from time import sleep
# 定义获取博主信息的函数
# 参数uid为博主的id
defget_user_info(uid):
# 发送请求
result = requests.get('https://m.weibo.cn/api/container/getIndex?type=uid&value={}'
.format(uid))
json_data = result.json() # 获取繁华信息中json内容
userinfo = {
'name': json_data['userInfo']['screen_name'], # 获取用户头像
'description': json_data['userInfo']['description'], # 获取用户描述
'follow_count': json_data['userInfo']['follow_count'], # 获取关注数
'followers_count': json_data['userInfo']['followers_count'], # 获取粉丝数
'profile_image_url': json_data['userInfo']['profile_image_url'], # 获取头像
'verified_reason': json_data['userInfo']['verified_reason'], # 认证信息
'containerid': json_data['tabsInfo']['tabs'][1]['containerid'] # 此字段在获取博文中需要
}
# 获取性别,微博中m表示男性,f表示女性
if json_data['userInfo']['gender'] == 'm':
gender = '男'
elif json_data['userInfo']['gender'] == 'f':
gender = '女'
else:
gender = '未知'
userinfo['gender'] = gender
return userinfo
# 获取古力娜扎信息
userinfo = get_user_info('1350995007')
# 信息如下
userinfo
{'containerid': '1076031350995007',
'description': '工作请联系:nazhagongzuo@163.com',
'follow_count': 529,
'followers_count': 12042995,
'name': '我是娜扎',
'profile_image_url': 'https://tvax2.sinaimg.cn/crop.0.0.1242.1242.180/50868c3fly8fevjzsp2j4j20yi0yi419.jpg',
'verified_reason': '演员,代表作《择天记》'}
In [33]:
# 循环获取所有博文
defget_all_post(uid,containerid):
# 从第一页开始
page = 0
# 这个用来存放博文列表
posts = []
while True:
# 请求博文列表
result = requests.get('https://m.weibo.cn/api/container/getIndex?type=uid&value={}&containerid={}&page={}'
.format(uid, containerid, page))
json_data = result.json()
# 当博文获取完毕,退出循环
if not json_data['cards']:
break
# 循环将新的博文加入列表
for i in json_data['cards']:
posts.append(i['mblog']['text'])
# 停顿半秒,避免被反爬虫
sleep(0.5)
# 跳转至下一页
page += 1
# 返回所有博文
return posts
posts = get_all_post('1350995007', '1076031350995007')
# 查看博文条数
len(posts)
1279
# 显示前3个
posts[:3]
至此,用户的数据已准备就绪,接下来开始生成用户画像。
二、生成用户画像
1.提取关键词
这里从博文列表中提取出关键字,分析出博主的发表的热词
import jieba.analyse
from html2text import html2text
content = '\n'.join([html2text(i) for i in posts])
# 这里使用jieba的textrank提取出1000个关键词及其比重
result = jieba.analyse.textrank(content, topK=1000, withWeight=True)
# 生成关键词比重字典
keywords = dict()
for i in result:
keywords[i[0]] = i[1]
2.生成词云图
from PIL import Image, ImageSequence
import numpy as np
import matplotlib.pyplot as plt
from wordcloud import WordCloud, ImageColorGenerator
# 初始化图片
image = Image.open('./static/images/personas.png')
graph = np.array(image)
# 生成云图,这里需要注意的是WordCloud默认不支持中文,所以这里需要加载中文黑体字库
wc = WordCloud(font_path='./fonts/simhei.ttf',
background_color='white', max_words=300, mask=graph)
wc.generate_from_frequencies(keywords)
image_color = ImageColorGenerator(graph)
# 显示图片
plt.imshow(wc)
plt.imshow(wc.recolor(color_func=image_color))
plt.axis("off") # 关闭图像坐标系
plt.show()
三、实现Flask应用
开发Flask不像Django那么复杂,小应用几个文件就可以完成。步骤如下:
1. 安装
使用pip安装flask,命令如下:
$ pip install flask
2.实现应用逻辑
简单来说,一个Flask应用就是一个Flask类,由route函数控制它的url请求。代码实现如下:
# app.pyfrom flask import Flask
import requests
from PIL import Image, ImageSequence
import numpy as np
import matplotlib.pyplot as plt
from wordcloud import WordCloud, ImageColorGenerator
import jieba.analyse
from html2text import html2text
from time import sleep
from collections import OrderedDict
from flask import render_template, request
# 创建一个Flask应用
app = Flask(__name__)
##################################
# 微博相关函数 #
# 定义获取博主信息的函数
# 参数uid为博主的id
def get_user_info(uid):
# 发送请求
result = requests.get('https://m.weibo.cn/api/container/getIndex?type=uid&value={}'
.format(uid))
json_data = result.json() # 获取繁华信息中json内容
# 获取性别,微博中m表示男性,f表示女性
if json_data['userInfo']['gender'] == 'm':
gender = '男'
elif json_data['userInfo']['gender'] == 'f':
gender = '女'
else:
gender = '未知'
userinfo = OrderedDict()
userinfo['昵称'] = json_data['userInfo']['screen_name'] # 获取用户头像
userinfo['性别'] = gender # 性别
userinfo['关注数'] = json_data['userInfo']['follow_count'] # 获取关注数
userinfo['粉丝数'] = json_data['userInfo']['followers_count'] # 获取粉丝数
userinfo['认证信息'] = json_data['userInfo']['verified_reason'] # 获取粉丝数
userinfo['描述'] = json_data['userInfo']['description'] # 获取粉丝数
data = {
'profile_image_url': json_data['userInfo']['profile_image_url'], # 获取头像
'containerid': json_data['tabsInfo']['tabs'][1]['containerid'], # 此字段在获取博文中需要
'userinfo': '<br>'.join(['{}:{}'.format(k, v) for (k,v) in userinfo.items()])
}
return data
# 循环获取所有博文
def get_all_post(uid, containerid):
# 从第一页开始
page = 0
# 这个用来存放博文列表
posts = []
while True:
# 请求博文列表
result = requests.get('https://m.weibo.cn/api/container/getIndex?type=uid&value={}&containerid={}&page={}'
.format(uid, containerid, page))
json_data = result.json()
# 当博文获取完毕,退出循环
if not json_data['cards']:
break
# 循环将新的博文加入列表
for i in json_data['cards']:
posts.append(i['mblog']['text'])
# 停顿半秒,避免被反爬虫
sleep(0.5)
# 跳转至下一页
page += 1
# 返回所有博文
return posts
##############################
## 云图相关函数
# 生成云图
def generate_personas(uid, data_list):
content = '<br>'.join([html2text(i) for i in data_list])
# 这里使用jieba的textrank提取出1000个关键词及其比重
result = jieba.analyse.textrank(content, topK=1000, withWeight=True)
# 生成关键词比重字典
keywords = dict()
for i in result:
keywords[i[0]] = i[1]
# 初始化图片
image = Image.open('./static/images/personas.png')
graph = np.array(image)
# 生成云图,这里需要注意的是WordCloud默认不支持中文,所以这里需要加载中文黑体字库
wc = WordCloud(font_path='./static/fonts/simhei.ttf',
background_color='white', max_words=300, mask=graph)
wc.generate_from_frequencies(keywords)
image_color = ImageColorGenerator(graph)
plt.imshow(wc)
plt.imshow(wc.recolor(color_func=image_color))
plt.axis("off") # 关闭图像坐标系
dest_img = './static/personas/{}.png'.format(uid)
plt.savefig(dest_img)
return dest_img
#######################################
# 定义路由
# 指定根路径请求的响应函数
@app.route('/', methods=['GET', 'POST'])
def index():
# 初始化模版数据为空
userinfo = {}
# 如果是一个Post请求,并且有微博用户id,则获取微博数据并生成相应云图
# request.method的值为请求方法
# request.form既为提交的表单
if request.method == 'POST' and request.form.get('uid'):
uid = request.form.get('uid')
userinfo = get_user_info(uid)
posts = get_all_post(uid, userinfo['containerid'])
dest_img = generate_personas(uid, posts)
userinfo['personas'] = dest_img
return render_template('index.html', **userinfo)
if __name__ == '__main__':
app.run()
以上就是全部的代码,简单吧?当然,单文件结构只适合小的应用,随着功能和代码量的增加,还是需要把代码分离中不同的文件结构中以便开发和维护。最后,还差一个页面的模版文件。
3.模版开发
模版需要有一个输入的表单和用户信息展示,基于Jinja2模版引擎。熟悉Django模版的应该可以很快上手,流程也和Django类型,在项目根目录下建一个名为templates的文件夹并新建一个名为index.html的文件,代码如下:
<!DOCTYPE html><html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="./static/css/style.css">
<title>Flask之微博单用户画像生成器</title>
</head>
<body>
<!--提交微博id的表单-->
<div>
<form action="/" method="post" id="search-form">
<input type="text" name="uid" class="search" placeholder="微博用户ID">
<input type="submit" class="submit" value="生成画像">
</form>
</div>
<!--下面是用户的展示信息-->
<!--使用了模版的if语法,如果有才展示这块内容-->
</body>
</html>
这样,应用实现完毕,项目结构如下:
$ tree .
weibo_personas
├── app.py
├── static
│ ├── css
│ │ └── style.css
│ ├── fonts
│ │ └── simhei.ttf
│ └── images
│ └── personas.png
└── templates
└── index.html
进入项目文件夹,启动项目:
$ python app.py
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
然后浏览器打开http://127.0.0.1:5000 地址就可以看到本教程最上面的效果。
以上只是一个初步实现,还有很多需要完善的地方。比如,如果发布的博文比较多时,获取时间比较长,可以考虑加个缓存,存储已获取的用户,避免重复请求,前端也可以加个loading效果。本教程展示的只是单用户,后面也可以批量获取用户信息,生成一个群体的用户画像
学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入学习交流群
626062078,我们一起学Python!
*请认真填写需求信息,我们会在24小时内与您取得联系。