[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<JsonIpinfodbLocationField>(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);

  

        return obj as JsonIpinfodbLocationField;

    }

    finally

    {

        if (webStream!=null)

            webStream.Close();

        if (streamReader!=null)

            streamReader.Close();

    }

}


再此感謝91哥的回覆。

你可能感兴趣的:(location)