[C#.NET][IP Location] 如何利用 JSON API 分析 IP Location

[C#.NET] 如何利用 JSON API 分析 IP Location


当我们知道一个IP Address后要如何更进一步的知道这个IP的资讯??在网络上爬了一段文,得知可以使用 http://ipinfodb.com/index.php 所提供的API来处理,这个网页提供了XML API以及JSON API,很可惜站上并无.NET的范例程序,只好自己动手处理,原理很简单,只要送出WebResquest后就能取得结果。

image

我们可以利用这个查询字符串,送出WebResquest,它就会回传相关字段了,下图是它回传的字段

image

程序开始前必须要向官网申请Key http://ipinfodb.com/register.php

建立字段类


[Serializable]
public class JsonIpinfodbLocationField
{
    public string StatusCode { get; set; }
    public string StatusMessage { get; set; }
    public string ipAddress { get; set; }
    public string CountryCode { get; set; }
    public string CountryName { get; set; }
    public string RegionName { get; set; }
    public string CityName { get; set; }
    public string ZipCode { get; set; }
    public string Latitude { get; set; }
    public string Longitude { get; set; }
    public string TimeZone { get; set; }
}


使用Json API

键入以下程序:


public JsonIpinfodbLocationField GetIpDetail(string ipAddress)
{
    string ip = string.Empty;
    Encoding sourceEncoding = Encoding.UTF8;
    string connectString = string.Format("http://api.ipinfodb.com/v3/ip-city/?key={0}&ip={1}&format=json", "输入自己申请的Key", ipAddress);

    StringBuilder ipInfo = new StringBuilder();
    Stream webStream = null;
    StreamReader streamReader = null;
    try
    {
        //1.取得Response串流
        webStream = WebRequest.Create(connectString).GetResponse().GetResponseStream();
        streamReader = new StreamReader(webStream, sourceEncoding);
        //2.分批读取到StringBuilder
        char[] buffer = new char[256];
        int readLength = streamReader.Read(buffer, 0, buffer.Length);
        while (readLength > 0)
        {
            byte[] dataArray = sourceEncoding.GetBytes(buffer, 0, readLength);
            ipInfo.Append(sourceEncoding.GetString(dataArray));
            readLength = streamReader.Read(buffer, 0, buffer.Length);
        }
        //3.利用JavaScriptSerializer反序列化处理Json
        JavaScriptSerializer scriptSerializer = new JavaScriptSerializer();
        object obj = scriptSerializer.Deserialize(ipInfo.ToString());

        return obj as JsonIpinfodbLocationField;
    }
    finally
    {
        if (webStream != null)
            webStream.Close();
        if (streamReader != null)
            streamReader.Close();
    }
}

PS.上面程序是分批读取,当然也可以直接用streamReader.ReadToEnd方法读取全部。

还没有反序列化前的数据长这样,看起来得再处理一下。

image

透过 JavaScriptSerializer 反序列化后得到了正确的结果,省掉了做苦工的时间。

image

PS.使用JavaScriptSerializer类时,必须要手动加入参考:System.Web.Extensions.dll

image


使用XML API

把json换成xml


public JsonIpinfodbLocationField GetIpDetail(string ipAddress)
{
    string ip = string.Empty;
    Encoding sourceEncoding = Encoding.UTF8;
    string connectString = string.Format("http://api.ipinfodb.com/v3/ip-city/?key={0}&ip={1}&format=xml", "输入自己申请的Key", ipAddress);

    StringBuilder ipInfo = new StringBuilder();
    Stream webStream = null;
    StreamReader streamReader = null;
    try
    {
        //1.取得Response串流
        webStream = WebRequest.Create(connectString).GetResponse().GetResponseStream();
        streamReader = new StreamReader(webStream, sourceEncoding);
        //2.分批读取到StringBuilder
        char[] buffer = new char[256];
        int readLength = streamReader.Read(buffer, 0, buffer.Length);
        while (readLength > 0)
        {
            byte[] dataArray = sourceEncoding.GetBytes(buffer, 0, readLength);
            ipInfo.Append(sourceEncoding.GetString(dataArray));
            readLength = streamReader.Read(buffer, 0, buffer.Length);
        }
        //3.读取xml
        return getXmlFormat(ipInfo.ToString());
    }
    finally
    {
        if (webStream != null)
            webStream.Close();
        if (streamReader != null)
            streamReader.Close();
    }
}

ipInfo 会得到XML结构,我试了一下,这个结构并没有办法可以直接反序列化的方式,如果有人试出来了麻烦告知我一下。

image

所以我就利用 XDocument 读取  Xml


JsonIpinfodbLocationField getXmlFormat(string ipInfo)
{
    JsonIpinfodbLocationField field = new JsonIpinfodbLocationField();
    XDocument doc = XDocument.Parse(ipInfo);

    field.CityName = doc.Elements().Select(a => a.Element("cityName").Value).FirstOrDefault();
    field.CountryCode = doc.Elements().Select(a => a.Element("countryCode").Value).FirstOrDefault();
    field.CountryName = doc.Elements().Select(a => a.Element("countryName").Value).FirstOrDefault();
    field.ipAddress = doc.Elements().Select(a => a.Element("ipAddress").Value).FirstOrDefault();
    field.Latitude = doc.Elements().Select(a => a.Element("latitude").Value).FirstOrDefault();
    field.Longitude = doc.Elements().Select(a => a.Element("longitude").Value).FirstOrDefault();
    field.RegionName = doc.Elements().Select(a => a.Element("regionName").Value).FirstOrDefault();
    field.StatusCode = doc.Elements().Select(a => a.Element("statusCode").Value).FirstOrDefault();
    field.StatusMessage = doc.Elements().Select(a => a.Element("statusMessage").Value).FirstOrDefault();
    field.TimeZone = doc.Elements().Select(a => a.Element("timeZone").Value).FirstOrDefault();
    field.ZipCode = doc.Elements().Select(a => a.Element("zipCode").Value).FirstOrDefault();

    return field;
}

最后所得到以下结果。

image


后记:

除了http://ipinfodb.com/index.php外还有一个网站也提供了相关的功能http://freegeoip.net/static/index.html,用法都大同小益

image


补充:

Xml没办法转的原因是我自己的问题,本以为透过Stream直接反序列就好了,没想到事实上并不是这样


XmlSerializer xml = new XmlSerializer(typeof(JsonIpinfodbLocationField));
object obj = xml.Deserialize(streamReader);

重新定义Entity类


[Serializable]
[XmlRoot("Response")]
public class JsonIpinfodbLocationField
{
    [XmlElement("statusCode")]
    public string StatusCode { get; set; }

    [XmlElement("statusMessage")]
    public string StatusMessage { get; set; }

    [XmlElement("ipAddress")]
    public string IpAddress { get; set; }

    [XmlElement("countryCode")]
    public string CountryCode { get; set; }

    [XmlElement("countryName")]
    public string CountryName { get; set; }

    [XmlElement("regionName")]
    public string RegionName { get; set; }

    [XmlElement("cityName")]
    public string CityName { get; set; }

    [XmlElement("zipCode")]
    public string ZipCode { get; set; }

    [XmlElement("latitude")]
    public string Latitude { get; set; }

    [XmlElement("longitude")]
    public string Longitude { get; set; }

    [XmlElement("timeZone")]
    public string TimeZone { get; set; }
}


改写Method,将字符串 data 丢到 MemoryStream 再反序列化即可


public JsonIpinfodbLocationField GetIpDetail(string ipAddress)
{
    string ip = string.Empty;
    Encoding sourceEncoding = Encoding.UTF8;
    string connectString = string.Format("http://api.ipinfodb.com/v3/ip-city/?key={0}&ip={1}&format=xml", "输入申请的KEY", ipAddress);

    StringBuilder ipInfo = new StringBuilder();
    Stream webStream = null;
    StreamReader streamReader = null;
    try
    {
        //1.取得Response串流
        webStream = WebRequest.Create(connectString).GetResponse().GetResponseStream();
        streamReader = new StreamReader(webStream, sourceEncoding);
        //2.分批读取到StringBuilder
        char[] buffer = new char[256];
        int readLength = streamReader.Read(buffer, 0, buffer.Length);
        while (readLength > 0)
        {
            byte[] dataArray = sourceEncoding.GetBytes(buffer, 0, readLength);
            ipInfo.Append(sourceEncoding.GetString(dataArray));
            readLength = streamReader.Read(buffer, 0, buffer.Length);
        }
        string data = ipInfo.ToString();

        byte[] byteArray = sourceEncoding.GetBytes(data);
        MemoryStream memoryStream = new MemoryStream(byteArray);

        XmlSerializer xml = new XmlSerializer(typeof(JsonIpinfodbLocationField));
        object obj = xml.Deserialize(memoryStream);
        if (obj == null)
            return null;

        return obj as JsonIpinfodbLocationField;
    }
    finally
    {
        if (webStream!=null)
            webStream.Close();
        if (streamReader!=null)
            streamReader.Close();
    }
}


再此感谢91哥的回复。

若有谬误,烦请告知,新手发帖请多包涵

2010~2017 C# 第四季