在上一篇文章详解阿里99大促活动页内容识别技术实现,我们介绍了在淘宝99大促中,我们使用了怎样的算法模型去识别并完成自动化测试的。
迫切解决的样本问题
淘宝大促有近百个模块、上千个页面,模块间具有相似性,并且模块内部具备多种状态,如果想要准确识别每个模块类型,单模块的样本数量至少要达到万级,而人工标注成本高、效率低下、数据量少,纯靠人力是无法满足模型诉求的。基于此,今天,我来介绍下,模型识别背后的大批量数据样本生成的技术方案。
总体技术方案如下:
模型的样本要求
算法模型识别的输入是99大促的各个会场截图,输出是目标模块名称及其在截图中的坐标位置。
模型训练时,就是把模块渲染图、相应坐标位置与模块类型输入给模型,交给模型去进行监督学习。而模型需要的,就是各个模块大批量的图片样本。
一个模块,是由View和ViewModel组合而成,而View是固定的,ViewModel跟随会场场景不同,是动态变化的。
那么,如果我们能拿到描述模块的View的这一层DSL,辅助以动态的ViewModel数据,再把View和ViewModel渲染成图片,那我们就可以生成无穷无尽的样本数据了。
DSL描述View
仔细梳理之后,View拆分为原子级元素(Text、Image、Shape)和原子级元素的组合关系(Group),即与HTML DOM树状结构中的各层级容器嵌套与叶子节点类型是同样的逻辑。
基于节点类型和节点样式的DSL,我们就能描述一个完整的View了。
{ "layers": [{ "frame": { "y": 354, "x": 44, "height": 32, "width": 312 }, "id": 2, "type": "text", "value": "Adidas Stan Smith", "textStyles": { "fontFamily": "Helvetica, sans-serif", "fontSize": 24 } }, { "frame": { "y": 0, "x": 384, "height": 342, "width": 342 }, "id": 3, "type": "image", "value": "//img.alicdn.com/bao/uploaded/i1/TB1.mcuNpXXXXctXFXXSutbFXXX.jpg_350x350Q50s50.jpg_.webp", "styles": { "height": 342, "width": 342 } }, { "frame": { "y": 0, "x": 384, "height": 342, "width": 342 }, "id": 4, "type": "shape", "styles": { "height": 342, "width": 342, "backgroundColor": "rgba(0, 0, 0, 0.1)" } }], "frame": { "y": 0, "x": 0, "height": 4920, "width": 750 }, "id": 1, "type": "group", "moduleName": "pmod-zebra-recommand-item" }
其中,除了节点类型和节点样式之外,最外层的moduleName代表模块名称,id是为了标记每一个子元素,frame是每个子元素的坐标位置、辅助算法模型识别模块内部子元素,value值只有text和image才有,对应相应的文本值还有图片链接。
获取模块View的DSL
有3种方案可以获取到模块View的DSL,分别是:
1、从代码仓库中获取;
2、从sketch视觉稿中生成;
3、从浏览器渲染好的页面中获取。
我最后选择了第三种方案,放弃第一个方案是因为代码写法千差万别,很多展现逻辑还包含在js代码中,并且还要处理各种for循环子View、style的映射关系等等,复杂度太高。第二个方案目前集团内已有技术方案imgcook,这一块的准确率听说还不错,并且一直在持续优化,而最终选择第三个方案的原因是,能100%准确地还原模块DSL,并且只需要关注模块最终展现给用户时候的形态,不需要理会过程中开发者做得各种复杂业务逻辑,复杂度相对低很多。
技术方案
在开发流程上,每个模块在开发完成后,都会有对应的模块预览页面。我使用了puppeteer模拟真实浏览器,对模块的节点信息进行提取,并保存为规范的DSL。
清洗window.getComputedStyle
通过window.getComputedStyle获取DOM节点的样式,会返回包含280个样式属性的对象,如果把每个DOM节点的所有280个样式属性都存储到DSL中,会造成两个问题:
1、DSL文件冗余,且文件大小过大,解析耗时;
2、增加算法同学对DSL的理解和调整成本。
第一步,隐藏默认属性值;
大部分的样式属性都是默认值,我们首先把默认的样式属性剔除出去。
{ alignSelf: 'auto', ... }
第二步,剔除无效属性;
开发者常用的样式属性在20个左右,有很多的样式是不具备实际效用的,把无效用的样式属性剔除掉,比如说:
{ zoom: '1', writingMode: 'horizontal-tb', ... }
第三步,transform动态计算
通过getComputedStyle拿到的transform属性值是一个矩阵方法matrix(),感兴趣的同学可以戳这里理解下2D转换矩阵。我们使用puppeteer模拟浏览器设置的屏幕宽度是750,也就是说,得到的transform值中translateX和translateY两个值是以750为基准换算得到的一个数字,假如想要在下面描述到的将DSL渲染成图时(算法同学期望能模拟各种各样的屏幕尺寸去生成样本),就必须将获取到的transform值换算成相应屏幕设备时的值。
# 为了方便算法同学更好使用DSL渲染成图的工具,这里使用python来实现 # screenshotShape是一个数组,代表屏幕宽高 [width, height] if 'transform' in style and 'matrix' in style['transform']: matrix = style['transform'][7:-1].split(',') translate = list(map(float, matrix[-2:])) translateResult = list(map(str, [distance*(screenshotShape[0]/750) for distance in translate])) matrix[-2:] = translateResult
通过以上3个步骤,最终得到的DOM节点样式属性个数一般维持在20个以内,能使输出的DSL精简非常多。
DSL渲染成图片
同样的,我们能基于puppeteer去对页面做操作,也能使用它去把DSL渲染成目标模块页面,并截图。
首先,建立DSL与HTML标签的映射关系
其次,如果是DSL类型为Group,就递归遍历里面的所有子元素,以此类推。
完整的渲染流程图如下:
ViewModel动态数据
一个模块,应用到99大促、双十一等各种会场,背后样式都是一致的,只有对应的数据不同,动态的数据一般是商品图片和商品信息。
闲鱼有一亿多的商品数据,如果把这商品数据拿过来与View一起渲染成模块,每个模块就有了成千上万种展现形态,且贴合算法模型实际识别过程中的输入,既能满足样本数量的要求,也能符合模型实际识别的场景,使模型准确率获得更大地提升。
效果
通过这样一条生成样本的通道,每个模块都能够提供给算法同学几万张质量很高的样本截图,使模型的准确率达到98%以上。
未来
上述文章描述了如何批量生成样本来帮助解决算法模型对99大促和双十一会场中各个模块的识别。
目前,对模块DSL的动态调整依赖算法同学对模块的理解,eg.改变圆角borderRadius生成更多正向样本,或者增加噪声,eg.删除商品内容节点等生成负向样本,这些操作都需要算法同学对DSL进行定制化配置。在未来,我们希望尝试把这部分的工作也交给模型去处理,让模型对样本生成做决策,调整DSL的局部,并生成样式更加丰富和可靠的样本。
作者:闲鱼技术-云听
里国际运营篇:阿里国际站的培训课程中都可以看到内页首部再次输入标题,并且对其使用<h2>标签,以此强调标题,提高排名权重的说法,那么这种看似神奇的操作是否行之有效呢?这篇文章从SEO的角度入手,解析一下<h2>的作用和用法。
培训讲解的<h2>标签用法:
目前看到的培训课程的说法是产品详情页的第一行或首部复制粘贴一遍标题,切换到HTML代码模式,给标题插入<h2>标签如:<h2>你的标题</h2>,目的是强调标题,提高搜索权重,以此提高排名
分析:
插入方式:<h2>标签用于文章的每一个分段文字的子标题,用于描述该段落的核心意思,一篇文章可以出现多次<h2>标签,分块描述不同的段落。所以SEO角度上看将产品标题再次复制加上<h2>的做法并不对爬虫方式:产品的标题已定义于<title>标签内,爬虫蜘蛛爬取过一遍<title>标签后,已获取文章标题和文章核心内容;进而深入爬取<h2>标签,意图获取不同文本段落的子标题,却再次在<h2>标签内爬取到和标题一模一样的内容,细致化一点来说这是内容堆砌,二次复制,对搜索引擎不友好阿里排名:官方规则文本上未看到<h2>标签有利于阿里搜索引擎爬取的明文,同时根据已知的阿里索引的方式为标题和属性这两个部分,内页详情页文本对排名没有影响(测试过内页填入自创的关键词,搜索0结果,无法排序)
结论:
从SEO角度看,<h2>标签对页面不同部分的重要性和内容解释性是有帮助,但是对Google排名的辅助作用是越来越小。相反页面的载入速度对排名的影响是越来越大(可以参考图片优化文章,优化图片大小,降低图片容量:https://www.losvincent.com/no-visitors.html)国际站这种二三级URL的产品页面,能够参与上google排名的可能性比独立站的首页页面(权重一般相对站内是最高)更小,个人搜索测试除非小竞争的长尾词下,大多数词基本较难有排名,所以阿里国际站的产品详情页在Google能产生排名的概率,可以相对忽略不计因此目前设置<h2>的方式,从SEO角度看是不对劲的写法;从Google排名效果看等于0
那么<H2>标签的正确用法是什么呢?
国外SEOer的解释是:H2 is for subheadings of that H1. Use it to divide content into scannable blocks; both Google and your visitor will like it. H3 is for subheadings of that H2
也就是说,<h2>标签和大学写论文一样,是定义每个段落或模块的子标题,或者说二级标题。因此从SEO角度看,目前国际站流行的<h2>标签用法是不太对劲的。下图是标配的正确用法:
正规的写法如下:
My h1 = <h1>H1, H2 and H3 Header Tags for SEO</h1>My h2 = <h2>Why are h1, h2 and h3 header tags important for SEO?</h2>My h3 = <h3>How to use the h1, h2 and h3 tags</h3>
<h2>标签可以出现多次,分别是对不同文章段落的概述
根据对国外客户网站的观察,发现如下现象:
<h1>标签被使用的概率小或者直接没有使用,这是因为一个页面最多建议出现一个<h1>标签,一般为标题或者最重要的核心文本部分,不过可能被滥用,Google似乎对<h1>标签有点禁忌<h2>标签出现在文章内容的不同段落作为段落子标题,或者出现在一些栏目等重要节点(如网站导航栏)
那么阿里国际站如何使用呢?
以2018 new design mobile phone case这个标题举例,写法方式为:
2018 new design mobile phone case(产品发布时填写的标题)
<h2>details of phone case</h2>
一段手机壳参数,性能描述的段落
<h2>生产工艺 of phone case</h2>
一段手机壳工艺流程的段落
<h2>支持型号of phone case</h2>
一段讲支持型号的的段落
面就是总结HTML5<meat>的标签:
<h2>一些常用的移动端的meta属性设置</h2> <!DOCTYPE html> <!-- 使用 HTML5 doctype,不区分大小写 --> <html lang="zh-cmn-Hans"> <!-- 更加标准的 lang 属性写法 http://zhi.hu/XyIa --> <head> <!-- 声明文档使用的字符编码 --> <meta charset='utf-8'> <!-- 优先使用 IE 最新版本和 Chrome --> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/> <!-- 页面描述 --> <meta name="description" content="不超过150个字符"/> <!-- 页面关键词 --> <meta name="keywords" content=""/> <!-- 网页作者 --> <meta name="author" content="name, email@gmail.com"/> <!-- 搜索引擎抓取 --> <meta name="robots" content="index,follow"/> <!-- 为移动设备添加 viewport --> <meta name="viewport" content="initial-scale=1, maximum-scale=3, minimum-scale=1, user-scalable=no"> <!-- `width=device-width` 会导致 iPhone 5 添加到主屏后以 WebApp 全屏模式打开页面时出现黑边 http://bigc.at/ios-webapp-viewport-meta.orz --> <!-- iOS 设备 begin --> <meta name="apple-mobile-web-app-title" content="标题"> <!-- 添加到主屏后的标题(iOS 6 新增) --> <meta name="apple-mobile-web-app-capable" content="yes"/> <!-- 是否启用 WebApp 全屏模式,删除苹果默认的工具栏和菜单栏 --> <meta name="apple-itunes-app" content="app-id=myAppStoreID, affiliate-data=myAffiliateData, app-argument=myURL"> <!-- 添加智能 App 广告条 Smart App Banner(iOS 6+ Safari) --> <meta name="apple-mobile-web-app-status-bar-style" content="black"/> <!-- 设置苹果工具栏颜色 --> <meta name="format-detection" content="telphone=no, email=no"/> <!-- 忽略页面中的数字识别为电话,忽略email识别 --> <!-- 启用360浏览器的极速模式(webkit) --> <meta name="renderer" content="webkit"> <!-- 避免IE使用兼容模式 --> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- 不让百度转码 --> <meta http-equiv="Cache-Control" content="no-siteapp" /> <!-- 针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓 --> <meta name="HandheldFriendly" content="true"> <!-- 微软的老式浏览器 --> <meta name="MobileOptimized" content="320"> <!-- uc强制竖屏 --> <meta name="screen-orientation" content="portrait"> <!-- QQ强制竖屏 --> <meta name="x5-orientation" content="portrait"> <!-- UC强制全屏 --> <meta name="full-screen" content="yes"> <!-- QQ强制全屏 --> <meta name="x5-fullscreen" content="true"> <!-- UC应用模式 --> <meta name="browsermode" content="application"> <!-- QQ应用模式 --> <meta name="x5-page-mode" content="app"> <!-- windows phone 点击无高光 --> <meta name="msapplication-tap-highlight" content="no"> <!-- iOS 图标 begin --> <link rel="apple-touch-icon-precomposed" href="/apple-touch-icon-57x57-precomposed.png"/> <!-- iPhone 和 iTouch,默认 57x57 像素,必须有 --> <link rel="apple-touch-icon-precomposed" sizes="114x114" href="/apple-touch-icon-114x114-precomposed.png"/> <!-- Retina iPhone 和 Retina iTouch,114x114 像素,可以没有,但推荐有 --> <link rel="apple-touch-icon-precomposed" sizes="144x144" href="/apple-touch-icon-144x144-precomposed.png"/> <!-- Retina iPad,144x144 像素,可以没有,但推荐有 --> <!-- iOS 图标 end --> <!-- iOS 启动画面 begin --> <link rel="apple-touch-startup-image" sizes="768x1004" href="/splash-screen-768x1004.png"/> <!-- iPad 竖屏 768 x 1004(标准分辨率) --> <link rel="apple-touch-startup-image" sizes="1536x2008" href="/splash-screen-1536x2008.png"/> <!-- iPad 竖屏 1536x2008(Retina) --> <link rel="apple-touch-startup-image" sizes="1024x748" href="/Default-Portrait-1024x748.png"/> <!-- iPad 横屏 1024x748(标准分辨率) --> <link rel="apple-touch-startup-image" sizes="2048x1496" href="/splash-screen-2048x1496.png"/> <!-- iPad 横屏 2048x1496(Retina) --> <link rel="apple-touch-startup-image" href="/splash-screen-320x480.png"/> <!-- iPhone/iPod Touch 竖屏 320x480 (标准分辨率) --> <link rel="apple-touch-startup-image" sizes="640x960" href="/splash-screen-640x960.png"/> <!-- iPhone/iPod Touch 竖屏 640x960 (Retina) --> <link rel="apple-touch-startup-image" sizes="640x1136" href="/splash-screen-640x1136.png"/> <!-- iPhone 5/iPod Touch 5 竖屏 640x1136 (Retina) --> <!-- iOS 启动画面 end --> <!-- iOS 设备 end --> <meta name="msapplication-TileColor" content="#000"/> <!-- Windows 8 磁贴颜色 --> <meta name="msapplication-TileImage" content="icon.png"/> <!-- Windows 8 磁贴图标 --> <link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml"/> <!-- 添加 RSS 订阅 --> <link rel="shortcut icon" type="image/ico" href="/favicon.ico"/> <!-- 添加 favicon icon --> <!-- sns 社交标签 begin --> <!-- 参考微博API --> <meta property="og:type" content="类型" /> <meta property="og:url" content="URL地址" /> <meta property="og:title" content="标题" /> <meta property="og:image" content="图片" /> <meta property="og:description" content="描述" /> <!-- sns 社交标签 end --> <title>标题</title> </head
下面是小编整理的一整套系统的前端学习教程,关注小编头条号,私信【前端】即可免费领取!
*请认真填写需求信息,我们会在24小时内与您取得联系。