一、背景

为了统计app访客数量来源所属地区,主要是省市的数量及其比例。

 

二、需求分析

通过haproxy的日志可以获取到每次请求的IP地址,通过查询IP地址的地区来统计。网路上有多种免费的IP地址转换的服务,考虑了准确性,易用性,查询速率以及每日查询量,最后决定使用百度的IP地址定位API。

普通IP定位 API是一个根据IP返回对应大致位置信息的HTTP/HTTPS形式位置服务接口。调用API接口,返回请求参数中指定IP的大致位置信息,包括:经纬度、省、市、区县等地址信息。如果请求参数中的IP为空,则默认返回当前服务请求来源的IP所对应的大致位置信息

 

三、说明文档

1、文档位置

百度地图开放平台---Web服务API---普通IP定位API,链接:

http://lbsyun.baidu.com/index.php?title=webapi/ip-api

注意事项:未认证的开发者账号每天配额查询IP数量为10W次,并发6k每分钟。

 

2、使用详细方法

使用方法

第一步,申请密钥(AK) ,作为访问服务的依据;

第二步,拼写发送HTTP/HTTPS请求的URL,注意需使用第一步申请的AK;

第三步,接收HTTP/HTTPS请求返回的数据(JSON格式)。

服务地址

http://api.map.baidu.com/location/ip

https://api.map.baidu.com/location/ip

接口参数:

参数

含义

格式

说明

ip

IP地址

string

可选,IP不出现,或者出现且为空字符串的情况下,会使用当前访问者的IP地址作为定位参数。

ak

开发者密钥

string

必选,登录API控制台,申请AK,作为访问的依据。

sn

用户的权限签名

string

可选,若用户所用AK的校验方式为SN校验时该参数必须。(SN生成算法)

coor

输出的坐标格式

string

可选,coor不出现时,默认为百度墨卡托坐标;coor=bd09ll时,返回为百度经纬度坐标。

 

返回值说明

返回结果(地址解析的结果)

{  

    address: "CN|北京|北京|None|CHINANET|1|None",    #地址  

    content:    #详细内容  

    {  

        address: "北京市",    #简要地址  

        address_detail:    #详细地址信息  

        {  

            city: "北京市",    #城市  

            city_code: 131,    #百度城市代码  

            district: "",    #区县  

            province: "北京市",    #省份  

            street: "",    #街道  

            street_number: ""    #门址  

        },  

        point:    #当前城市中心点  

        {  

            x: "116.39564504",  

            y: "39.92998578"  

        }  

    },  

    status: 0    #返回状态码  }

注:若返回异常,请查看 异常返回状态码 ,确认异常原因。

接口示例

http://api.map.baidu.com/location/ip?ak=请输入您的AK&coor=bd09ll

https://api.map.baidu.com/location/ip?ak=请输入您的AK&coor=bd09ll

返回值:

{  

    address: "CN|吉林|长春|None|CERNET|1|None",  

    content: 

    {  

        address: "吉林省长春市",  

        address_detail: 

        {  

            city: "长春市",  

            city_code: 53,  

            district: "",  

            province: "吉林省",  

            street: "",  

            street_number: ""  

        },  

        point:  #当前城市中心点

        {       

            x: "125.31364243",      

            y: "43.89833761"  

        }  

    },  

    status: 0  }

 

Python代码

import urllib2

import json

def ip_to_addr(ip,ak):

try:

url='https://api.map.baidu.com/location/ip?ip='+str(ip)+'&ak=ak&coor=bd09ll'

                response = urllib2.urlopen(url,timeout=3)

                html = response.read()

                decoded = json.loads(html)

                status = decoded['status']

                if status == 0:

                        province = decoded['content']['address_detail']['province']

                        city = decoded['content']['address_detail']['city']

                        return status,province,city

                else:return status

        except Exception as e:

                return 999

 

四、设计

1、在haproxy服务器,用shell脚本(static_haprxy_log.sh)将前一天的日志清洗过滤及统计,生成文本文件,文本每行只有两个字段,IP地址和此IP地址的请求数。然后将文本传到处理数据的主机(免密码scp)。

>$ cat static_haprxy_log.sh

#!/bin/bash

DIR='/apps/logs/haproxy/rotate'

cd $DIR

filename='haproxy.log.'$(date -d "1 days ago" +%F)

filename_s='haproxy.static.'$(date -d "1 days ago" +%F)'.txt'

filename_s_old='haproxy.static.'$(date -d "11 days ago" +%F)'.txt'

awk '{print $6}' $filename |awk -F: '{print $1}' |sort|uniq -c|sort -k 1 -nr > $filename_s

sed -i 's/^ \{1,9\}//g' $filename_s

scp $filename_s root@$IP://apps/logs/haproxy_statick/

rm -f $filename_s_old

注意:$IP为处理数据的主机的IP地址。

2、接收到数据文本的主机,首先用shell脚本(filter.sh)排除白名单的IP地址(调用接口的IP地址),再用Python脚本(insertMySQL.py)将数据写到MySQL数据库表中。数据库表5个有用字段:IP地址,IP地址请求次数,API返回状态码,省,市。

>$ cat filter.sh

#!/bin/bash

cd '/apps/logs/haproxy_statick'

filename_s='haproxy.static.'$(date -d "1 days ago" +%F)'.txt'

cat /apps/sh/whiteList.txt |while read line

do

sed -i "/$line/d" $filename_s

done

filename_old='haproxy.static.'$(date -d "11 days ago" +%F)'.txt'

rm -f $filename_old

3、运行Python程序(insertMySQL.py),将查到的IP地址对应的省,市,返回码更新到数据库表。