使用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":"\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
下面就来看看穷举程序如何写:
importre
defipv3_to_int(s):
l=[int(i)foriins.split('.')]
return(l[0]<<16)|(l[1]<<8)|l[2]
defint_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()
foriplistinlist:
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]
foripinrange(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接口进行抓取了,抓取代码如下:
#!/usr/bin/python
#-*-coding:utf-8-*-
importurllib,urllib2,simplejson,sqlite3,time
defipv3_to_int(s):
l=[int(i)foriins.split('.')]
return(l[0]<<16)|(l[1]<<8)|l[2]
defint_to_ipv4(s):
ip1=s>>16&0xFF
ip2=s>>8&0xFF
ip3=s&0xFF
return"%d.%d.%d.0"%(ip1,ip2,ip3)
deffetch(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)
printurl
fails=0
try:
result=simplejson.load(urllib2.urlopen(url,timeout=20))
except(urllib2.URLError,IOError):
fails+=1
iffails<10:
result=fetch(ipv4)
else:
sleep_download_time=60*10
time.sleep(sleep_download_time)
result=fetch(ipv4)
returnresult
defdbcreate():
c=conn.cursor()
c.execute('''createtableipdata(
ipintegerprimarykey,
retinteger,
starttext,
endtext,
countrytext,
provincetext,
citytext,
districttext,
isptext,
typetext,
desctext
)''')
conn.commit()
c.close()
defdbinsert(ip,address):
c=conn.cursor()
c.execute('insertintoipdatavalues(?,?,?,?,?,?,?,?,?,?,?)',(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()forsini.readlines()]
end=0
foripinlist:
ip=int(ip)
ifip>end:
ipaddress=int_to_ipv4(ip)
info=fetch(ipaddress)
ifinfo['ret']==-1:
pass
else:
dbinsert(ip,info)
end=ipv3_to_int(info['end'])
printip,end
else:
pass
i.close()
到此就能把新浪所有的国内IP数据给抓取出来,然后在数据分析的工程中大派用场。~