【问题标题】:PHP - Get exact iOS version from User-AgentPHP - 从 User-Agent 获取准确的 iOS 版本
【发布时间】:2017-12-28 15:19:06
【问题描述】:

我想从 User-Agent 获取 PHP 中的确切 iOS 版本。我很清楚伪造用户代理的可能性,但就我而言,这不是问题。

一个普通的 iPhone 用户代理字符串如下所示:

Mozilla/5.0 (iPhone; CPU iPhone OS 11_2_1 like Mac OS X) AppleWebKit/604.4.7 (KHTML, like Gecko) Version/11.0 Mobile/15C153 Safari/604.1

如何从中提取操作系统版本?在这种情况下,它是“11_2_1”。我必须能够从 iPhone、iPad 和 iPod 用户代理中提取它。它也可以是 X_X 而不是 X_X_X。

到目前为止,我得到了这个:

<?php
$version = preg_match('(iPad|iPhone|iphone|iPod).*?(OS |os |OS\_)(\d+
((_|\.)\d)?((_|\.)\d)?)', $_SERVER['HTTP_USER_AGENT']);
echo $version;
?>

但是,从 iPhone 访问它会显示一个空白页面。有人可以帮帮我吗?

提前致谢。

【问题讨论】:

  • i(?:phone|pad|pod) os ([\d_]+)i(?:phone|pad|pod) os \K[\d_]+ip(?:hone|[ao]d) os \K[\d_]+?
  • 注意 preg_match() 在错误时返回 false,不会回显。你可能想要var_dump()
  • @AlexHowansky 返回 bool(false);
  • @ctwheels 抱歉,我有点迷路了……经验不足。
  • @Johnny 给我一点时间来发布答案

标签: php ios regex user-agent


【解决方案1】:

代码

您可以执行多个正则表达式来获取操作系统版本。下面的正则表达式可能是最快的:

See regex in use here

ip(?:hone|[ao]d) os \K[\d_]+

注意:这些正则表达式都使用i 标志。

也可以使用其他变体,例如:

i(?:phone|pad|pod) os \K[\d_]+
i(?:phone|pad|pod) os ([\d_]+)

用法

See code in use here

<?php

$re = '/ip(?:hone|[ao]d) os \K[\d_]+/i';
$str = 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_2_1 like Mac OS X) AppleWebKit/604.4.7 (KHTML, like Gecko) Version/11.0 Mobile/15C153 Safari/604.1';
preg_match($re, $str, $matches, PREG_OFFSET_CAPTURE, 0);
var_dump($matches);

注意:要分隔结果中的每个版本部分,您可以使用以下行as shown here

var_dump(explode("_", $matches[0][0]));

用法 - 使用 OP 的代码

<?php

$re = '/ip(?:hone|[ao]d) os \K[\d_]+/i';
preg_match($re, $_SERVER['HTTP_USER_AGENT'], $matches, PREG_OFFSET_CAPTURE, 0);
var_dump($matches);

结果

输入

Mozilla/5.0 (iPhone; CPU iPhone OS 11_2_1 like Mac OS X) AppleWebKit/604.4.7 (KHTML, like Gecko) Version/11.0 Mobile/15C153 Safari/604.1

输出

输出匹配:

11_2_1

_ 上输出与explode() 的匹配项(见第一个用法 部分下的注释):

11
2
1

说明

  • ip 逐字匹配
  • (?:hone|[ao]d) 匹配以下任意一项
    • hone 从字面上匹配(使iphone
    • [ao]d 匹配ao 后跟d(使ipadipod
  • 匹配文字空格字符
  • os 按字面意思匹配
  • 匹配文字空格字符。我注意到 OP 也有 OS\_,这让我认为这里可能存在下划线字符。如果是这样的话this can be changed to [ _] instead
  • \K 重置比赛的起点。任何先前使用的字符都将从最终匹配中排除
  • [\d_]+ 匹配一个或多个任意数字或下划线字符

【讨论】:

  • 感谢您的精彩解释 - 工作得很好!
  • @Johnny 不客气!如果您需要澄清任何事情,请告诉我:)
【解决方案2】:

这应该可以完成工作:

$version = preg_match("/OS ((\d+_?){2,3})/i", $_SERVER['HTTP_USER_AGENT'], $matches);
print_r(str_replace("_",".",$matches[1]));

【讨论】:

  • 这里只返回“11”,而目标浏览器是11_2_1。
【解决方案3】:

您可以使用用户代理解析器,甚至可以创建自己的解析器。 Here你有一个例子,我也找到了这个php项目PhpUserAgent,应该很简单使用:

$result = parse_user_agent($ua);

然后您可以从该对象中提取version

这个用于 javascript 的 user-agent-parser 也很好用。

【讨论】:

    【解决方案4】:

    尝试使用这个:"/(i(?:phone|pad|pod)) OS (\d+_\d+_\d+)/i"

    【讨论】:

    • 是的,忘记在最后添加i 以进行不区分大小写的匹配。谢谢。
    • 这不适用于Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X) AppleWebKit/534.46 ...
    • @TommasoBelluzzo 这种情况有点令人困惑,因为它没有按照给出的示例进行格式化。在CPU 之后,我假设存在像iphone 这样的字符串。这似乎是一个 eLRuLL 没有提到的技巧案例。而且它与 ctwheels 给出的答案不匹配。
    猜你喜欢
    • 1970-01-01
    • 2021-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-07
    • 2018-03-06
    • 1970-01-01
    • 2011-12-26
    相关资源
    最近更新 更多