在 C# .Net 中使用 browscap.ini 或 xml
Using browscap.ini or xml with C# .Net
我今天在 C# 土地上。 我正在尝试编写一个接受用户代理字符串和 returns 至少给我浏览器名称和版本的对象的函数。 所以我尝试了 this answer,但它报告 Chrome 为 AppleMAC-Safari 5.0。误报最流行的浏览器真是不能接受。
我可以访问 browscap.ini 或 XML 或 JSON。似乎我必须手动执行此操作,但这些文件中的正则表达式与 C# 中的正则表达式不兼容。这有点像噩梦。
我正在使用 Visual Studio 和 .Net 3.5。
很高兴您提出这个问题!它一直困扰着我。基本上您要做的是获取并解析其中一个 browscap 文件。我使用了 XML 文件。从那里,您必须根据您的用户代理字符串检查每个正则表达式模式。在XML文件中,即每个browscapitem的"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 并获取这些值。这不是我的专业领域,所以我只是做了足够的工作来让它发挥作用。在我的 class 中,我有:
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);
}
}
}
}
}
}
剩下的只是填写 "parent" 属性的一些技巧。因此,一旦找到匹配项,就必须返回并找到其父项及其父项的父项等。
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");
我今天在 C# 土地上。 我正在尝试编写一个接受用户代理字符串和 returns 至少给我浏览器名称和版本的对象的函数。 所以我尝试了 this answer,但它报告 Chrome 为 AppleMAC-Safari 5.0。误报最流行的浏览器真是不能接受。
我可以访问 browscap.ini 或 XML 或 JSON。似乎我必须手动执行此操作,但这些文件中的正则表达式与 C# 中的正则表达式不兼容。这有点像噩梦。
我正在使用 Visual Studio 和 .Net 3.5。
很高兴您提出这个问题!它一直困扰着我。基本上您要做的是获取并解析其中一个 browscap 文件。我使用了 XML 文件。从那里,您必须根据您的用户代理字符串检查每个正则表达式模式。在XML文件中,即每个browscapitem的"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 并获取这些值。这不是我的专业领域,所以我只是做了足够的工作来让它发挥作用。在我的 class 中,我有:
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);
}
}
}
}
}
}
剩下的只是填写 "parent" 属性的一些技巧。因此,一旦找到匹配项,就必须返回并找到其父项及其父项的父项等。
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");