python抓取新浪国内IP地址数据
功能:
使用Python程序抓取新浪在国内的所有IP的教程
数据分析,特别是网站分析中需要对访问者的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":"u4e2du56fd","province":"u5317u4eac","city":"u5317u4eac","district":"","isp":"u8054u901a","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、穷举程序代码:
复制代码 代码示例:
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()
2、对新浪IP接口进行抓取:
复制代码 代码示例:
#!/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数据,在数据分析的工程中会很用。