浏览器访问网站时,会提交UserAgent信息,里面包含操作系统/浏览器类型/渲染引擎,可以据此大致评估网站的客户端分布。特别是移动设备会在UserAgent中包含设备型号信息,所以有可能根据UserAgent分析移动设备类型,进而针对不同设备实施改善用户体验等优化工作。
看一个UserAgent的例子:
Mozilla/5.0 (Linux; Android 4.4.2; Che2-TL00M Build/HonorChe2-TL00M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36
这是来从Android 4.4.2的华为手机Che2-TL00M的HTTP请求中提取出来的UserAgent信息,使用浏览器是Chrome30. 很多网站会根据UserAgent信息判断应该如何给客户端应答。但由于UserAgent内容没有规范可循,各个浏览器厂家可以自行定义其内容,甚至普通用户可以在访问网站时,通过工具自行修改UserAgent信息,比如Chrome就可以干这件事。各浏览器厂商为了服务器判断时得到赦免,会加入Mozilla/Safari/AppleWebKit/Geko等字样,都是欺诈。因此,网站服务器收到的UserAgent不一定完全准确,但能动手修改UA信息的人毕竟占少数,如果网站流量比较大,从UA中提取的信息还是能大致看到客户端的分布状况。
如何得到UserAgent?首先从AccessLog中提取UserAgent字段,一般CDN或者采用W3C(IIS)或者采用NCSA(Apache)都有标准的格式,网络上也有很多提取UA的方法。
提取出来的UserAgent如何解析?可以自己写正则表达式解析你想要的信息,不过要想应付种类繁杂的操作系统/浏览器版本,还是要下一番功夫的。好在,有人已经做了这件事,并公开了源码:
https://github.com/HaraldWalker/user-agent-utils
这个小工具很方便,通过一行代码:UserAgent.parseUserAgentString(ua),可以提取
设备类型:Computer / Mobile / Tablet / Game Console / Wearable 等;
操作系统:Windows x / Linux / Android / Mac OS / iOS / Blackberry / Chrome OS / MeeGo / Symbian / BADA 等,几乎都有了,包括操作系统版本;
浏览器:IE / Edge / Firefox / Safari / Chrome / OPERA / DOLFIN / THUNDERBIRD / SEAMONKEY 等,还有很多没用过甚至没听说过的;
试用了一下,速度还是很快的。但有些问题:
问题1,设备类型对Tablet的判断有些混乱,把Red Mi和索爱 LT26i / LT29i等都判断成Tablet,查看代码发现它是根据操作系统关键字判断设备类型,其Android操作系统数据结构定义:
// commented by , many devices can not be distinguished as mobile or tablet just by [whether it's useragent contails "mobile"]
ANDROID( OSManufacturer.GOOGLE,null, 0, "Android", new String[] { "Android" }, new String[] {"Ubuntu"}, DeviceType.MOBILE, null ),
ANDROID5( OSManufacturer.GOOGLE,OperatingSystem.ANDROID, 5, "Android 5.x", new String[] { "Android 5", "Android-5" }, new String[] { "glass" }, DeviceType.MOBILE, null ),
//ANDROID5_TABLET(OSManufacturer.GOOGLE,OperatingSystem.ANDROID5, 50, "Android 5.x Tablet", new String[] { "Android 5", "Android-5"}, new String[] { "mobile", "glass"}, DeviceType.TABLET, null ),
ANDROID4( OSManufacturer.GOOGLE,OperatingSystem.ANDROID, 4, "Android 4.x", new String[] { "Android 4", "Android-4" }, new String[] { "glass", "ubuntu"}, DeviceType.MOBILE, null ),
//ANDROID4_TABLET(OSManufacturer.GOOGLE,OperatingSystem.ANDROID4, 40, "Android 4.x Tablet", new String[] { "Android 4", "Android-4"}, new String[] { "mobile", "glass", "ubuntu"}, DeviceType.TABLET, null ),
//ANDROID4_WEARABLE(OSManufacturer.GOOGLE,OperatingSystem.ANDROID, 400, "Android 4.x", new String[] { "Android 4" }, new String[] {"ubuntu"}, DeviceType.WEARABLE, null ),
//ANDROID3_TABLET(OSManufacturer.GOOGLE,OperatingSystem.ANDROID, 30, "Android 3.x Tablet", new String[] { "Android 3" }, null, DeviceType.TABLET, null ), // as long as there are not Android 3.x phones this should be enough
ANDROID2( OSManufacturer.GOOGLE,OperatingSystem.ANDROID, 2, "Android 2.x", new String[] { "Android 2" }, null, DeviceType.MOBILE, null ),
//ANDROID2_TABLET(OSManufacturer.GOOGLE,OperatingSystem.ANDROID2, 20, "Android 2.x Tablet", new String[] { "Kindle Fire", "GT-P1000","SCH-I800" }, null, DeviceType.TABLET, null ),
ANDROID1( OSManufacturer.GOOGLE,OperatingSystem.ANDROID, 1, "Android 1.x", new String[] { "Android 1" }, null, DeviceType.MOBILE, null ),
可以看到Android->Android x ->Android x Tablet 是一个嵌套结构,并且alias定义new String[] { "Android 4", "Android-4" }在Mobile和Tablet是一样的,正是用aliases关键字对UA信息进行设备类型判断的, 在判断的时候,会优先深度遍历这个嵌套,如果UA中不包含mobile字样,就判定为Tablet,如果包含mobile字样,就判定为Mobile,这在上面提到的小米和索爱等机型上不适用,造成Tablet统计结果有很大偏差。所以我将Android Tablet的定义都屏蔽了,统计结果中Android机型统一当作Mobile设备。
问题2,设备类型不支持智能电视,很多厂家已经推出Android电视,确实有用户用它访问网站,但应该是小众用户,对总体分析结果影响不大,如果关注来自TV的流量,可自行添加判断逻辑
问题3,浏览器不包含对国产品牌360,搜狗,世界之窗,UC等的支持,需要自己添加相应品牌的识别逻辑
问题4,不能提取移动设备品牌信息,我自己添加了国内常见品牌的提取逻辑,实验了一下,提取结果片段如下(从左至右:DeviceType, DeviceBrand, OS, Browser, PV)
从结果看,Android机型的Browser中频繁出现Mobile Safari,所以这个小工具对Browser的提取不太理想。
折腾了近一天一夜,终于可以对UserAgent做分析报告了。