12

我正在寻找一种方法来分析用户代理字符串以确定它们是否由移动设备生成。这需要基于 java 并且可用于 hadoop 上的大批量日志文件分析以生成统计信息(即,不适合使用 Web 服务)。

我见过WURFL,但鉴于我只需要二进制移动/非移动响应,许可费似乎令人望而却步。

到目前为止,我一直在使用UADetector,这几乎正是我所需要的。但是,我遇到了一些限制。在我的测试中,我发现许多用户代理字符串提供了足够的信息来确定用户代理来自移动设备,但被 UADetector 报告为 UNKNOWN。

例如,标准差的 Android 应用可以发送 UA 字符串“Android”。这足以知道它来自移动设备,但 UADetector 将此 UserAgentType 报告为 UNKNOWN 而不是 MOBILE_BROWSER。

Apache Mobile FilterLite Device Detection是正确的,但我需要一些可以从 Java 中使用的东西。

谁能推荐一个更好的解决方案?

4

5 回答 5

6

我是 MobileESP 项目的创始人和维护者,这是一个用于检测移动设备的免费开源跨平台库。它仍然非常活跃!:-)

www.mobileesp.org

MobileESP给出二进制“是移动的”响应。您可以按 iOS、Android 或 Windows Phone 等平台或按设备类别(如“iPhone Tier”智能手机与平板电脑)进行检测。请务必快速查看 API 页面。

您可能知道,用户代理字符串变化很大。如果设备附带浏览器,制造商可能会对其进行定制。例如,HTC 经常自定义原生 Android 浏览器的用户代理字符串。

Google 提供了有关 OEM 应如何自定义用户代理的建议。如果该设备应被视为手机,则 Google 建议在字符串中包含单词“mobile”元素。但如果该设备应被视为平板电脑,则该字符串不应包含“mobile”。当然,对这一建议的遵守情况差异很大。

像 Opera 或 Maxthon 这样的第三方浏览器可以在用户代理字符串中放入任何他们想要的东西——然后就可以了!某些“新”浏览器将保持无名,在为每个平台(例如,Android 与 iOS 版本)在其用户代理字符串中放置正确信息方面做得很差。除非您从这些浏览器获得大量流量并希望投资于跟踪每个平台和软件版本的确切用户代理值,否则您无能为力。

无论如何,MobileESP 的创建目的是在提供页面时逐页进行检测。我也特意编写了易于阅读和自定义的代码。

要进行批处理,您可以执行以下操作:

1.) 在构造函数中,注释掉 initDeviceScan() 方法。您不需要它来进行批量处理。

2.) 将 UserAgent 和一个空字符串传递给构造函数 (UAgentInfo())。

3.) 然后运行您感兴趣的任何检测方法。根据对用户的扫描,仔细考虑执行它们的顺序以节省时间。

例如,如果您的大多数用户都使用 iPhone,并且这是您感兴趣的检测标准之一,那么首先运行该检查。如果是这个例子,你肯定不会先运行 BlackBerry 方法!

我的联系信息在源代码和网站上。如果您有任何问题或遇到任何错误,请给我发送便条。一定要在 MobileESP.org 网站上查看一些提示。

祝您项目顺利,Aniket!

  • 安东尼
于 2013-12-09T01:45:44.267 回答
4

另一个线程建议使用以下库:

https://github.com/ahand/mobileesp/blob/master/Java/UAgentInfo.java

这似乎没问题。

于 2013-09-17T09:10:28.767 回答
2

如何读取 JSP 中的 Apache Mobile Filter 值(对于 Tomcat)?

在必须配置 mod_jk 的 httpd.conf 文件之前,您必须添加以下内容:

JkEnvVar AMF_IS_MOBILE undefined

Java代码是:

request.getAttribute("AMF_IS_MOBILE")

来自:http ://wiki.apachemobilefilter.org

于 2013-03-12T22:40:05.093 回答
2

51Degrees 有一个免费的开源 Java API,允许您运行离线处理。您可以从此处的 GitHub 存储库访问它。https://github.com/51Degrees/Java-Device-Detection

作为 API 的一部分,有一个离线处理示例(代码如下所示),它采用用户代理的 CSV 文件并将所需的属性返回到输出文件中。以下示例仅使用数据集中的 3 个属性,完整列表您可以在此处查看字典https://51degrees.com/resources/property-dictionary

// output file in current working directory
public String outputFilePath = "batch-processing-example-results.csv";
// pattern detection matching provider
private final Provider provider;

/**
 * Initialises the device detection Provider with the included Lite data
 * file. For more data see: 
 * <a href="https://51degrees.com/compare-data-options">compare data options
 * </a>
 * 
 * @throws IOException if there was a problem reading from the data file.
 */
public OfflineProcessingExample() throws IOException {
    provider = new Provider(StreamFactory.create(
            Shared.getLitePatternV32(), false));
 }

/**
 * Reads a CSV file containing User-Agents and adds the IsMobile, 
 * PlatformName and PlatformVersion information for the first 20 lines.
 * For a full list of properties and the files they are available in please 
 * see: <a href="https://51degrees.com/resources/property-dictionary">
 * Property Dictionary</a>
 * 
 * @param inputFileName the CSV file to read from.
 * @param outputFilename where to save the file with extra entries.
 * @throws IOException if there was a problem reading from the data file.
 */
public void processCsv(String inputFileName, String outputFilename) 
        throws IOException {
    BufferedReader bufferedReader = 
            new BufferedReader(new FileReader(inputFileName));
    try {
        FileWriter fileWriter = new FileWriter(outputFilename);
        try {
            // it's more efficient over the long haul to create a match 
            // once and reuse it in multiple matches
            Match match = provider.createMatch();
            // there are 20k lines in supplied file, we'll just do a couple 
            // of them!
            for (int i = 0; i < 20; i++) {

                // read next line
                String userAgentString = bufferedReader.readLine();

                // ask the provider to match the UA using match we created
                provider.match(userAgentString, match);

                // get some property values from the match
                Values isMobile = match.getValues("IsMobile");
                Values platformName = match.getValues("PlatformName");
                Values platformVersion = match.getValues("PlatformVersion");

                // write result to file
                fileWriter.append("\"")
                        .append(userAgentString)
                        .append("\", ")
                        .append(getValueForDisplay(isMobile))
                        .append(", ")
                        .append(getValueForDisplay(platformName))
                        .append(", ")
                        .append(getValueForDisplay(platformVersion))
                        .append('\n')
                        .flush();
            }
        } finally {
            fileWriter.close();
        }
    } finally {
        bufferedReader.close();
    }
}

/**
 * Match values may be null. A helper method to get something displayable
 * @param values a Values to render
 * @return a non-null String
 */
protected String getValueForDisplay(Values values) {
    return values == null ? "N/A": values.toString();
} 

/**
 * Closes the {@link fiftyone.mobile.detection.Dataset} by releasing data 
 * file readers and freeing the data file from locks. This method should 
 * only be used when the {@code Dataset} is no longer required, i.e. when 
 * device detection functionality is no longer required, or the data file 
 * needs to be freed.
 * 
 * @throws IOException if there was a problem accessing the data file.
 */
@Override
public void close() throws IOException {
    provider.dataSet.close();
}

/**
 * Instantiates this class and starts 
 * {@link #processCsv(java.lang.String, java.lang.String)} with default 
 * parameters.
 * 
 * @param args command line arguments.
 * @throws IOException if there was a problem accessing the data file.
 */
public static void main(String[] args) throws IOException {
    System.out.println("Starting Offline Processing Example");
    OfflineProcessingExample offlineProcessingExample = 
            new OfflineProcessingExample();
    try {
        offlineProcessingExample.processCsv(Shared.getGoodUserAgentsFile(), 
                offlineProcessingExample.outputFilePath);
        System.out.println("Output written to " + 
                offlineProcessingExample.outputFilePath);
    } finally {
        offlineProcessingExample.close();
    }
}

希望这可以帮助。

披露:我在 51Degrees 工作。

于 2017-04-12T11:39:42.927 回答
0

可以使用检测iPhone、Android等移动设备Java user-agent。如果您使用的是 Spring,您可以根据需要自定义以下代码。

@Override
public ModelAndView redirectToAppstore(HttpServletRequest request) {
    String userAgent = request.getHeader("user-agent").toLowerCase();
    String iphoneStoreUrl = "IPONE_STORE_URL";
    String androidStoreUrl = "ANDROID_STORE_URL";
    if (userAgent.contains("iphone"))
        return new ModelAndView("redirect:" + iphoneStoreUrl);
    else if (userAgent.contains("android"))
        return new ModelAndView("redirect:" + androidStoreUrl);

    return new ModelAndView("redirect:/");
}
于 2016-04-11T05:22:13.853 回答