User-Agent 字符串没有规则,因此无法创建完全正确且面向未来的解析器。但有一个一般模式:
User-Agent: <engine-string> <engine-string> ...
Where engine-string
有形式:
<agent-name> (<comment>; <comment>; ...)
每个引擎字符串(我只是根据我的理解称呼它,这可能不正确)可能有也可能没有注释。
例如:
Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) ↲
AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e ↲
Safari/8536.25 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
(这是一个字符串,我只是将其分成几行。)似乎,每当有人对浏览器引擎进行分叉时,他们只是将其内容附加到末尾。所以我们有一些抽象的“Mozilla”浏览器(“第一次浏览器战争”的遗产),它认为它在 iPhone 上。然后我们看到有一个WebKit(它记得很久以前它是作为KHTML诞生的)。然后还有一些Version/6.0的修改,后来修改成了Mobile/10A5376e,又变成了Safari/8536.25,终于揭开了它其实是移动Google bot的秘密。
另一个例子:
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB7.4; ↲
InfoPath.1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; ↲
.NET CLR 3.5.30729; .NET CLR 1.1.4322)
这是一个单引擎,但括号里有很多话要说。
所以一般观察是:
- 最后的引擎弦是最重要的,
- 括号中的最后一条评论不太重要。
考虑到这一点,我的想法是将字符串解析为这些引擎和注释标记,然后从每个引擎部分丢弃从第五个开始的注释。然后,如果仍然不够,则从第二个开始丢弃引擎部分(第一个通常是抽象的“Mozilla”,但通常有有用的注释;有时它实际上是具体的东西,特别是对于网络爬虫而言)。
在解析时,我们需要考虑到偶尔可能会有不遵循这种格式的字符串。它们可以保存到日志文件中以供以后检查,然后简单地剪切到所需的长度以适合数据库。