2015-02-03 2 views
1

Я сегодня на C#. Я пытаюсь написать функцию, которая принимает строку агента пользователя и возвращает объект, который дает мне хотя бы имя и версию браузера. Так я пробовал this answer, но он сообщает Chrome как AppleMAC-Safari 5.0. Это не очень приемлемо для неправильного представления наиболее популярного браузера.Использование browscap.ini или xml с C# .Net

У меня есть доступ к browscap.ini или XML или JSON. Кажется, что я должен сделать это вручную, но регулярное выражение в этих файлах не совместимо с регулярным выражением на C#. Это своего рода кошмар.

Я использую Visual Studio и .Net 3.5.

+1

Агент пользователя строка для Chrome 40.0.2214.94 m - «Mozilla/5.0 (Windows NT 6.1, WOW64) AppleWebKit/537.36 (KHTML, например, Gecko) Chrome/40.0.2214.94 Safari/537.36'. Он содержит Chrome/, поэтому вы можете использовать Regex. Осмотрите строки пользовательского агента других браузеров, которые вы хотите поддержать, и сделайте что-то подобное. Есть ли что-то важное для бизнеса, чтобы определить, какой браузер использует пользователь? – adamdc78

+0

@ adamdc78 Я бы не сказал, что это важно для бизнеса. Я просто записываю, с кем пользователи браузеров входят в систему. Я заработал на PHP за несколько минут, но в C# это кажется невозможным. Может быть, даже проще использовать C# для вызова простого PHP-скрипта на этом этапе ... – Andrew

ответ

1

Я так рад, что вы задали этот вопрос! Это беспокоило меня навсегда. В основном, что вам нужно сделать, это получить и проанализировать один из файлов броузера. Я использовал XML-файл. Оттуда вы должны проверить каждый шаблон регулярного выражения на строку вашего пользовательского агента. В XML-файле это атрибут «name» каждого браузера.

Однако шаблоны в файле должны быть преобразованы в реальное регулярное выражение, поэтому C# их поймет. Это основной метод, необходимый для вашей проблемы. Все остальное - это просто вопрос разбора разных типов файлов.

(я использовал this code, чтобы посмотреть, что другие сделали, чтобы заставить его работать в PHP.)

public static Boolean BrowserPatternMatches(string pattern, string input) 
{ 
    string patternConverted = "^" + pattern 
       .Replace("\\", "\\\\") 
       .Replace(".", "\\.") 
       .Replace("?", ".") 
       .Replace("*", ".*") 
       .Replace("$", "\\$") 
       .Replace("[", "\\[") 
       .Replace("]", "\\]") 
       .Replace("|", "\\|") 
       .Replace("(", "\\(") 
       .Replace(")", "\\)") 
       .Replace("+", "\\+") 
       .Replace("{", "\\{") 
       .Replace("}", "\\}") 
       .Replace("%", "\\%") 
       + "$"; 
    Regex regex = new Regex(patternConverted); 
    return regex.IsMatch(input); 
} 

Это мясо проблемы. Остальное - это разбор XML и получение этих значений. Это НЕ моя область знаний, поэтому я просто сделал достаточно, чтобы получить ее функциональность. В моем классе у меня есть:

private Dictionary<string, Dictionary<string, string>> dic = new Dictionary<string, Dictionary<string, string>>(); 

private void FillDictionary() 
{ 
    if (this.dic.Count == 0) 
    { 
     XmlTextReader reader = new XmlTextReader("browscap.xml"); 

     while (reader.Read()) 
     { 
      if (reader.Name == "browscapitem") 
      { 
       string pattern = reader.GetAttribute("name"); 
       if (pattern != null) 
       { 
        if (!this.dic.ContainsKey(pattern)) 
        { 
         Dictionary<string, string> properties = new Dictionary<string, string>(); 
         while (reader.Read()) 
         { 
          if (reader.Name == "browscapitem") 
          { 
           break; 
          } 
          if (reader.GetAttribute("name") != null) 
          { 
           properties.Add(reader.GetAttribute("name").ToLower(), reader.GetAttribute("value")); 
          } 
         } 
         this.dic.Add(pattern, properties); 
        } 
       } 
      } 
     } 
    } 
} 

Остальное - это просто некоторые хитрости, чтобы заполнить «родительские» свойства. Поэтому, как только вы найдете матч, вы должны вернуться назад и найти его родителей и родителей его родителя и т.д.

private Dictionary<string, string> GetBrowserProps(string parentId) 
{ 
    return this.dic[parentId]; 
} 

public Dictionary<string, string> GetBrowserObject(string uaString) 
{ 
    this.FillDictionary(); 

    bool found = false; 
    string foundKey = ""; 

    foreach (string pattern in this.dic.Keys) 
    { 
     if (!found) 
     { 
      found = RecordBrowsers.BrowserPatternMatches(pattern, uaString); 
      if (found) { foundKey = pattern; break; } 
     } 
    } 

    Dictionary<string, string> browserProps = new Dictionary<string, string>(); 
    if (foundKey != "") 
    { 
     browserProps = this.GetBrowserProps(foundKey); 
     Dictionary<string, string> current = this.GetBrowserProps(foundKey); 
     bool cont = current.ContainsKey("parent"); 
     while (cont) 
     { 
      Dictionary<string, string> parent = this.GetBrowserProps(current["parent"]); 
      foreach (string s in parent.Keys) 
      { 
       if (!browserProps.ContainsKey(s)) 
       { 
        browserProps.Add(s, parent[s]); 
       } 
      } 
      current = parent; 
      cont = current.ContainsKey("parent"); 
     } 
    } 

    return browserProps; 
} 

Вот мои тесты для хорошей мерой:

Console.WriteLine("RecordBrowser started"); 

string[] strs = { "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.94 Safari/537.36", 
        "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0", 
        "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.94 Safari/537.36 OPR/27.0.1689.66", 
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.94 Safari/537.36", 
        "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.8pre) Gecko/20070928 Firefox/2.0.0.7 Navigator/9.0RC1", 
        "Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20121202 Firefox/17.0 Iceweasel/17.0.1"}; 

string[] expectedResults = { "Chrome 40.0", "Firefox 35.0", "Opera 27.0", "Chrome 40.0", "Netscape 9.0", "Iceweasel 17.0" }; 

for(int i=0; i<strs.Length; i++) 
{ 
    Dictionary<string, string> browserProps = this.GetBrowserObject(strs[i]); 
    if (browserProps["comment"] == expectedResults[i]) 
    { 
     Console.WriteLine("test " + i + " passed"); 
    } 
    else 
    { 
     Console.WriteLine("test " + i + " failed"); 
    } 
    Console.WriteLine("**********************************************************"); 
} 
Console.WriteLine("DONE");