数据分析,特别是网站分析中需要对访问者的IP进行分析,分析IP中主要是区分来访者的省份+城市+行政区数据,考虑到目前纯真IP数据库并没有把这些数据做很好的区分,于是寻找了另外一个可行的方案(当然不是花钱买哈)。解决方案就是抓取新浪的IP数据。
新浪的IP数据接口为:
http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip=123.124.2.85
返回的数据为:
{"ret":1,"start":"123.123.221.0","end":"123.124.158.29","country":"\u4e2d\u56fd","province":"\u5317\u4eac","city":"\u5317\u4eac","district":"","isp":"\u8054\u901a","type":"","desc":""}
其返回的内容中已经包含了省份+城市+行政区信息了,这就是我们真实想要的。
下面就来说说如何来抓取这部分IP数据,要抓取这部分数据的主要工作就是枚举,即将接口中的IP不断的替换,要替换所有的IP地址肯定不太可能,所以我们缩小下范围,只穷举所有中国的IP段。考虑到新浪的IP接口返回的是IP段,所以要穷举的部分又少了一部分。再考虑啊到IP段的最后一位及256个IP基本上都是在一个地区,所以我们要穷举的数据有少了很多。对于穷举最重要的是把IP地址换成INT型。
具体国内有多少IP地址段,可以到APNIC官方网站去查找或下面的文档
http://ftp.apnic.net/apnic/dbase/data/country-ipv4.lst
下面就来看看穷举程序如何写:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
import re def ipv3_to_int(s): l = [ int (i) for i in s.split( '.' )] return (l[ 0 ] << 16 ) | (l[ 1 ] << 8 ) | l[ 2 ] def int_to_ipv3(s): ip1 = s >> 16 & 0xFF ip2 = s >> 8 & 0xFF ip3 = s & 0xFF return "%d.%d.%d" % (ip1, ip2, ip3) i = open ( 'ChinaIPAddress.csv' , 'r' ) list = i.readlines() for iplist in list : pattern = re. compile ( '(\d{1,3}\.\d{1,3}\.\d{1,3})\.\d{1,3}' ) ips = pattern.findall(iplist) x = ips[ 0 ] y = ips[ 1 ] for ip in range (ipv3_to_int(x),ipv3_to_int(y)): ipadress = str (ip) #ip_address = int_to_ipv3(ip) o = open ( 'ChinaIPAddress.txt' , 'a' ) o.writelines(ipadress) o.writelines( '\n' ) o.close() i.close() |
当上面的不走完成后就可以对新浪IP接口进行抓取了,抓取代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
#!/usr/bin/python # -*- coding: utf-8 -*- import urllib,urllib2, simplejson, sqlite3, time def ipv3_to_int(s): l = [ int (i) for i in s.split( '.' )] return (l[ 0 ] << 16 ) | (l[ 1 ] << 8 ) | l[ 2 ] def int_to_ipv4(s): ip1 = s >> 16 & 0xFF ip2 = s >> 8 & 0xFF ip3 = s & 0xFF return "%d.%d.%d.0" % (ip1, ip2, ip3) def fetch(ipv4, * * kwargs): kwargs.update({ 'ip' : ipv4, 'format' : 'json' , }) DATA_BASE = "http://int.dpool.sina.com.cn/iplookup/iplookup.php" url = DATA_BASE + '?' + urllib.urlencode(kwargs) print url fails = 0 try : result = simplejson.load(urllib2.urlopen(url,timeout = 20 )) except (urllib2.URLError,IOError): fails + = 1 if fails < 10 : result = fetch(ipv4) else : sleep_download_time = 60 * 10 time.sleep(sleep_download_time) result = fetch(ipv4) return result def dbcreate(): c = conn.cursor() c.execute( '''create table ipdata( ip integer primary key, ret integer, start text, end text, country text, province text, city text, district text, isp text, type text, desc text )''' ) conn.commit() c.close() def dbinsert(ip,address): c = conn.cursor() c.execute( 'insert into ipdata values(?,?,?,?,?,?,?,?,?,?,?)' ,(ip,address[ 'ret' ],address[ 'start' ],address[ 'end' ],address[ 'country' ],address[ 'province' ],address[ 'city' ],address[ 'district' ],address[ 'isp' ],address[ 'type' ],address[ 'desc' ])) conn.commit() c.close() conn = sqlite3.connect( 'ipaddress.sqlite3.db' ) dbcreate() i = open ( 'ChinaIPAddress.txt' , 'r' ) list = [s.strip() for s in i.readlines()] end = 0 for ip in list : ip = int (ip) if ip > end : ipaddress = int_to_ipv4(ip) info = fetch(ipaddress) if info[ 'ret' ] = = - 1 : pass else : dbinsert(ip,info) end = ipv3_to_int(info[ 'end' ]) print ip,end else : pass i.close() |
到此就能把新浪所有的国内IP数据给抓取出来,然后在数据分析的工程中大派用场。~