一、背景
为了统计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地址对应的省,市,返回码更新到数据库表。