2011年12月22日 星期四

如何利用 JSON API 分析 IP Location

當我們知道一個IP Address後要如何更進一步的知道這個IP的資訊??在網路上爬了一段文,得知可以使用 http://ipinfodb.com/index.php 所提供的API來處理,這個網頁提供了XML API以及JSON API,很可惜站上並無.NET的範例程式碼,只好自己動手處理,原理很簡單,只要送出WebResquest後就能取得結果。

程式開始前必須要向官網申請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;
    //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());
    if (obj == null)
        return null;
    else
        return (JsonIpinfodbLocationField)obj;
}
PS.上面程式碼是分批讀取,當然也可以直接用streamReader.ReadToEnd方法讀取全部。
還沒有反序列化前的資料長這樣,看起來得再處理一下。
image 
透過 JavaScriptSerializer 反序列化後得到了正確的結果,省掉了做苦工的時間。
image

PS.使用JavaScriptSerializer類別時,必須要手動加入參考:System.Web.Extensions.dll

使用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;
    //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());
}

ipInfo 會得到XML結構,我試了一下,這個結構並沒有辦法可以直接反序列化的方式,如果有人試出來了麻煩告知我一下。

所以我就利用 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;
}
 
 
 
原始文章出此 













沒有留言:

張貼留言