使用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数据给抓取出来,然后在数据分析的工程中大派用场。~