PAST ARTICLE · Program
PHP で IP から各携帯キャリアの判定

PHP で IP から各携帯キャリアの判定で「(http://d.hatena.ne.jp/tasukuchan/20071231/1199105717)」を使わせてもらっていて、最新版があるのか調べてみたら、「「PHPで高速に携帯ゲートウェイのIPから携帯キャリアを判別する」を更新する | グニャラくんのwktk運営日記」で公開されていました。ただ、Docomo SP モード がなかったので追加してみました。
出力されるスクリプトは下記で、ip2long にして二分探索されています。詳細は、上記のリンク先で説明されていますので省略します。
<?php
/*
This script is generated by scrape.py at 2012-04-21 10:29:25.
http://svn.coderepos.org/share/lang/python/cidr-mobilejp/trunk/scrape.py
*/
function ip2mobile($ip) {
$n = sprintf('%u', ip2long($ip));
if ($n < 1914014208) {
if ($n < 1867942952) {
if ($n < 998277120) {
if ($n < 21905408) {
if ($n < 21780480) {
if ($n < 21495808) {
if ($n >= 21127168 && $n <= 21129727) {
return 'docomosp';
}
} else if ($n <= 21754879) {
return 'docomosp';
} else {
if ($n >= 21757952 && $n <= 21778431) {
return 'docomosp';
}
}
} else if ($n <= 21811199) {
return 'docomosp';
} else {
if ($n < 21846016) {
if ($n >= 21813248 && $n <= 21843967) {
return 'docomosp';
}
} else if ($n <= 21876735) {
return 'docomosp';
} else {
if ($n < 21878784) {
} else if ($n <= 21900287) {
return 'docomosp';
} else {
if ($n >= 21905408 && $n <= 21913599) {
return 'docomosp';
}
}
}
}
} else if ($n <= 21921791) {
return 'docomosp';
} else {
if ($n < 21929984) {
if ($n < 21921792) {
if ($n >= 21913600 && $n <= 21915391) {
return 'docomosp';
}
} else if ($n <= 21929983) {
return 'docomosp';
} else {
if ($n >= 21921792 && $n <= 21938175) {
return 'docomosp';
}
}
} else if ($n <= 21932031) {
return 'docomosp';
} else {
if ($n < 22003712) {
if ($n >= 21938176 && $n <= 21999615) {
return 'docomosp';
}
} else if ($n <= 22011903) {
return 'docomosp';
} else {
if ($n < 828375040) {
} else if ($n <= 828391423) {
return 'docomosp';
} else {
if ($n >= 828507904 && $n <= 828510463) {
return 'docomosp';
}
}
}
}
}
} else if ($n <= 998281215) {
return 'ezweb';
} else {
if ($n < 1036427264) {
if ($n < 1036419072) {
if ($n < 998713216) {
if ($n >= 998712960 && $n <= 998713087) {
return 'ezweb';
}
} else if ($n <= 998713247) {
return 'ezweb';
} else {
if ($n >= 1031078432 && $n <= 1031078447) {
return 'ezweb';
}
}
} else if ($n <= 1036421631) {
return 'airhphone';
} else {
if ($n < 1036421888) {
if ($n >= 1036421732 && $n <= 1036421735) {
return 'airhphone';
}
} else if ($n <= 1036421895) {
return 'airhphone';
} else {
if ($n < 1036422016) {
} else if ($n <= 1036422063) {
return 'airhphone';
} else {
if ($n >= 1036422144 && $n <= 1036423167) {
return 'airhphone';
}
}
}
}
} else if ($n <= 1036429055) {
return 'airhphone';
} else {
if ($n < 1036779520) {
if ($n < 1036449792) {
if ($n >= 1036429312 && $n <= 1036431359) {
return 'airhphone';
}
} else if ($n <= 1036451839) {
return 'airhphone';
} else {
if ($n >= 1036451584 && $n <= 1036451839) {
return 'airhphone';
}
}
} else if ($n <= 1036779775) {
return 'airhphone';
} else {
if ($n < 1036803072) {
if ($n >= 1036780032 && $n <= 1036781439) {
return 'airhphone';
}
} else if ($n <= 1036804095) {
return 'airhphone';
} else {
if ($n < 1856177664) {
} else if ($n <= 1856179711) {
return 'docomosp';
} else {
if ($n >= 1856231424 && $n <= 1856234495) {
return 'docomosp';
}
}
}
}
}
}
} else if ($n <= 1867942975) {
return 'ezweb';
} else {
if ($n < 1913928448) {
if ($n < 1913925888) {
if ($n < 1867944704) {
if ($n < 1867943552) {
if ($n >= 1867943232 && $n <= 1867943487) {
return 'ezweb';
}
} else if ($n <= 1867943743) {
return 'ezweb';
} else {
if ($n >= 1867943872 && $n <= 1867943935) {
return 'ezweb';
}
}
} else if ($n <= 1867944959) {
return 'ezweb';
} else {
if ($n < 1869313024) {
if ($n >= 1868034432 && $n <= 1868034447) {
return 'ezweb';
}
} else if ($n <= 1869313151) {
return 'ezweb';
} else {
if ($n < 1869313216) {
} else if ($n <= 1869313231) {
return 'ezweb';
} else {
if ($n >= 1913925888 && $n <= 1913926143) {
return 'airhphone';
}
}
}
}
} else if ($n <= 1913926399) {
return 'airhphone';
} else {
if ($n < 1913927168) {
if ($n < 1913926400) {
if ($n >= 1913926144 && $n <= 1913926655) {
return 'airhphone';
}
} else if ($n <= 1913926911) {
return 'airhphone';
} else {
if ($n >= 1913926656 && $n <= 1913927423) {
return 'airhphone';
}
}
} else if ($n <= 1913927679) {
return 'airhphone';
} else {
if ($n < 1913927680) {
if ($n >= 1913927424 && $n <= 1913927935) {
return 'airhphone';
}
} else if ($n <= 1913928191) {
return 'airhphone';
} else {
if ($n < 1913927936) {
} else if ($n <= 1913928447) {
return 'airhphone';
} else {
if ($n >= 1913928192 && $n <= 1913928703) {
return 'airhphone';
}
}
}
}
}
} else if ($n <= 1913928959) {
return 'airhphone';
} else {
if ($n < 1914011648) {
if ($n < 1913929472) {
if ($n < 1913928960) {
if ($n >= 1913928704 && $n <= 1913929215) {
return 'airhphone';
}
} else if ($n <= 1913929471) {
return 'airhphone';
} else {
if ($n >= 1913929216 && $n <= 1913929727) {
return 'airhphone';
}
}
} else if ($n <= 1913929983) {
return 'airhphone';
} else {
if ($n < 1913929984) {
if ($n >= 1913929728 && $n <= 1913930239) {
return 'airhphone';
}
} else if ($n <= 1913930495) {
return 'airhphone';
} else {
if ($n < 1913930240) {
} else if ($n <= 1913930751) {
return 'airhphone';
} else {
if ($n >= 1913930496 && $n <= 1913930751) {
return 'airhphone';
}
}
}
}
} else if ($n <= 1914011903) {
return 'airhphone';
} else {
if ($n < 1914012928) {
if ($n < 1914011904) {
if ($n >= 1914011648 && $n <= 1914012159) {
return 'airhphone';
}
} else if ($n <= 1914012415) {
return 'airhphone';
} else {
if ($n < 1914012160) {
} else if ($n <= 1914012927) {
return 'airhphone';
} else {
if ($n >= 1914012672 && $n <= 1914013183) {
return 'airhphone';
}
}
}
} else if ($n <= 1914013439) {
return 'airhphone';
} else {
if ($n < 1914013440) {
if ($n >= 1914013184 && $n <= 1914013695) {
return 'airhphone';
}
} else if ($n <= 1914013951) {
return 'airhphone';
} else {
if ($n < 1914013696) {
} else if ($n <= 1914014207) {
return 'airhphone';
} else {
if ($n >= 1914013952 && $n <= 1914014463) {
return 'airhphone';
}
}
}
}
}
}
}
} else if ($n <= 1914014719) {
return 'airhphone';
} else {
if ($n < 2098990592) {
if ($n < 1989727872) {
if ($n < 1914016512) {
if ($n < 1914015232) {
if ($n < 1914014720) {
if ($n >= 1914014464 && $n <= 1914014975) {
return 'airhphone';
}
} else if ($n <= 1914015231) {
return 'airhphone';
} else {
if ($n >= 1914014976 && $n <= 1914015487) {
return 'airhphone';
}
}
} else if ($n <= 1914015743) {
return 'airhphone';
} else {
if ($n < 1914015744) {
if ($n >= 1914015488 && $n <= 1914015999) {
return 'airhphone';
}
} else if ($n <= 1914016255) {
return 'airhphone';
} else {
if ($n < 1914016000) {
} else if ($n <= 1914016511) {
return 'airhphone';
} else {
if ($n >= 1914016256 && $n <= 1914016767) {
return 'airhphone';
}
}
}
}
} else if ($n <= 1914017023) {
return 'airhphone';
} else {
if ($n < 1914044160) {
if ($n < 1914017024) {
if ($n >= 1914016768 && $n <= 1914017279) {
return 'airhphone';
}
} else if ($n <= 1914017279) {
return 'airhphone';
} else {
if ($n >= 1914043904 && $n <= 1914043935) {
return 'airhphone';
}
}
} else if ($n <= 1914044191) {
return 'airhphone';
} else {
if ($n < 1966539104) {
if ($n >= 1914044160 && $n <= 1914044191) {
return 'airhphone';
}
} else if ($n <= 1966539199) {
return 'emobile';
} else {
if ($n < 1966539232) {
} else if ($n <= 1966539263) {
return 'emobile';
} else {
if ($n >= 1966555392 && $n <= 1966555407) {
return 'emobile';
}
}
}
}
}
} else if ($n <= 1989727999) {
return 'ezweb';
} else {
if ($n < 2070736240) {
if ($n < 1990165952) {
if ($n < 1990165664) {
if ($n >= 1990165248 && $n <= 1990165375) {
return 'ezweb';
}
} else if ($n <= 1990165695) {
return 'ezweb';
} else {
if ($n >= 1990165760 && $n <= 1990165887) {
return 'ezweb';
}
}
} else if ($n <= 1990166015) {
return 'ezweb';
} else {
if ($n < 2037375904) {
if ($n >= 2037375744 && $n <= 2037375871) {
return 'ezweb';
}
} else if ($n <= 2037375935) {
return 'ezweb';
} else {
if ($n < 2037376768) {
} else if ($n <= 2037376895) {
return 'ezweb';
} else {
if ($n >= 2070736128 && $n <= 2070736159) {
return 'softbank';
}
}
}
}
} else if ($n <= 2070736271) {
return 'softbank';
} else {
if ($n < 2098988800) {
if ($n < 2070736864) {
if ($n >= 2070736352 && $n <= 2070736383) {
return 'softbank';
}
} else if ($n <= 2070736895) {
return 'softbank';
} else {
if ($n < 2098987008) {
} else if ($n <= 2098988799) {
return 'airhphone';
} else {
if ($n >= 2098988544 && $n <= 2098989055) {
return 'airhphone';
}
}
}
} else if ($n <= 2098989311) {
return 'airhphone';
} else {
if ($n < 2098989824) {
if ($n >= 2098989824 && $n <= 2098990079) {
return 'airhphone';
}
} else if ($n <= 2098990335) {
return 'airhphone';
} else {
if ($n < 2098990080) {
} else if ($n <= 2098990591) {
return 'airhphone';
} else {
if ($n >= 2098990336 && $n <= 2098990847) {
return 'airhphone';
}
}
}
}
}
}
} else if ($n <= 2098991615) {
return 'airhphone';
} else {
if ($n < 3541233152) {
if ($n < 3532785600) {
if ($n < 3405602960) {
if ($n < 3075129344) {
if ($n >= 3075080192 && $n <= 3075082751) {
return 'docomosp';
}
} else if ($n <= 3075131903) {
return 'docomosp';
} else {
if ($n >= 3405602816 && $n <= 3405602847) {
return 'softbank';
}
}
} else if ($n <= 3405602991) {
return 'softbank';
} else {
if ($n < 3405603728) {
if ($n >= 3405603040 && $n <= 3405603071) {
return 'softbank';
}
} else if ($n <= 3405603759) {
return 'softbank';
} else {
if ($n < 3414864896) {
} else if ($n <= 3414865407) {
return 'docomosp';
} else {
if ($n >= 3414870784 && $n <= 3414871039) {
return 'docomosp';
}
}
}
}
} else if ($n <= 3532785663) {
return 'softbank';
} else {
if ($n < 3538206148) {
if ($n < 3534314496) {
if ($n >= 3534288384 && $n <= 3534288895) {
return 'airhphone';
}
} else if ($n <= 3534316543) {
return 'airhphone';
} else {
if ($n >= 3538206140 && $n <= 3538206143) {
return 'softbank';
}
}
} else if ($n <= 3538206151) {
return 'softbank';
} else {
if ($n < 3539975680) {
if ($n >= 3538321632 && $n <= 3538321647) {
return 'ezweb';
}
} else if ($n <= 3539975935) {
return 'airhphone';
} else {
if ($n < 3539975680) {
} else if ($n <= 3539975935) {
return 'airhphone';
} else {
if ($n >= 3541231616 && $n <= 3541233407) {
return 'airhphone';
}
}
}
}
}
} else if ($n <= 3541233663) {
return 'airhphone';
} else {
if ($n < 3681328384) {
if ($n < 3681288704) {
if ($n < 3548299392) {
if ($n >= 3541233408 && $n <= 3541233663) {
return 'airhphone';
}
} else if ($n <= 3548299519) {
return 'airhphone';
} else {
if ($n >= 3681288704 && $n <= 3681288959) {
return 'airhphone';
}
}
} else if ($n <= 3681289215) {
return 'airhphone';
} else {
if ($n < 3681289216) {
if ($n >= 3681288960 && $n <= 3681289471) {
return 'airhphone';
}
} else if ($n <= 3681289727) {
return 'airhphone';
} else {
if ($n < 3681289472) {
} else if ($n <= 3681289983) {
return 'airhphone';
} else {
if ($n >= 3681289728 && $n <= 3681292287) {
return 'airhphone';
}
}
}
}
} else if ($n <= 3681328511) {
return 'ezweb';
} else {
if ($n < 3715563520) {
if ($n < 3681328680) {
if ($n >= 3681328640 && $n <= 3681328671) {
return 'ezweb';
}
} else if ($n <= 3681328687) {
return 'ezweb';
} else {
if ($n < 3682439424) {
} else if ($n <= 3682439551) {
return 'ezweb';
} else {
if ($n >= 3682439680 && $n <= 3682439695) {
return 'ezweb';
}
}
}
} else if ($n <= 3715565055) {
return 'airhphone';
} else {
if ($n < 3724642368) {
if ($n >= 3715564800 && $n <= 3715566079) {
return 'airhphone';
}
} else if ($n <= 3724642431) {
return 'ezweb';
} else {
if ($n < 3724885632) {
} else if ($n <= 3724885759) {
return 'ezweb';
} else {
if ($n >= 3725542592 && $n <= 3725542655) {
return 'ezweb';
}
}
}
}
}
}
}
}
return 'pc';
}
?>ip2mobile.php を出力する Python のコードで追加、修正したものは下記です。
- Docomo SP モードの追加
- Softbank の URL を変更
- Emobile の追加。ただし、公開されている情報が古いです。
- UQ WIMAX は情報が公開されていなかったので追加できず・・・
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re
import urllib
from datetime import datetime
DEBUG = False
class Docomo(object):
def name(self):
return 'docomo'
def url(self):
return 'http://www.nttdocomo.co.jp/service/imode/make/content/ip/'
def run(self):
content = urllib.urlopen(self.url()).read()
n = self.name()
return [(ip, n) for ip in re.findall(r'<li>(\d+\.\d+\.\d+\.\d+/\d+)[^<]*</li>', content, re.M)]
class DocomoSP(object):
def name(self):
return 'docomosp'
def url(self):
return 'http://www.nttdocomo.co.jp/service/developer/smart_phone/technical_info/etc/index.html'
def run(self):
content = urllib.urlopen(self.url()).read()
n = self.name()
pattern = '(\d+\.\d+\.\d+\.\d+/\d+)'
result = re.findall(pattern, content, re.M)
pattern = '(\d+\.\d+\.\d+\.\d+/\d+)\s*?\x81\x60\s*?(\d+\.\d+\.\d+\.\d+/\d+)'
ip_ranges = re.findall(pattern, content, re.M)
for ip_range in ip_ranges:
pattern = '(\d+)\.(\d+)\.(\d+)\.(\d+)/(\d+)'
ip = re.findall(pattern, ip_range[0], re.M) + re.findall(pattern, ip_range[1], re.M)
if ip[0][4] == ip[1][4]:
i = int(ip[0][4])/8-1
start = int(ip[0][i])
end = int(ip[1][i]) + 1
for j in range(start, end):
if i == 0:
result.append(str(j) + '.' + ip[0][1] + '.' + ip[0][2] + '.' + ip[0][3] + '/' + ip[0][4])
elif i == 1:
result.append(ip[0][0] + '.' + str(j) + '.' + ip[0][2] + '.' + ip[0][3] + '/' + ip[0][4])
elif i == 2:
result.append(ip[0][0] + '.' + ip[0][1] + '.' + str(j) + '.' + ip[0][3] + '/' + ip[0][4])
elif i == 3:
result.append(ip[0][0] + '.' + ip[0][1] + '.' + ip[0][2] + '.' + str(j) + '/' + ip[0][4])
return [(ip, n) for ip in list(set(result))]
class Ezweb(object):
def name(self):
return 'ezweb'
def url(self):
return 'http://www.au.kddi.com/ezfactory/tec/spec/ezsava_ip.html'
def run(self):
content = urllib.urlopen(self.url()).read()
n = self.name()
pattern = r'<td>\s*<div class="TableText">([\d\.]+)</div>\s*</td>\s+<td>\s*<div class="TableText">(/\d+)</div>\s*</td>'
return [(ip + sn, n) for ip, sn in re.findall(pattern, content, re.M)]
class Softbank(object):
def name(self):
return 'softbank'
def url(self):
return 'http://creation.mb.softbank.jp/mc/tech/tech_web/web_ipaddress.html'
def run(self):
content = urllib.urlopen(self.url()).read()
n = self.name()
pattern = r'<th>(\d+\.\d+\.\d+\.\d+/\d+)</th>'
return [(ip, n) for ip in re.findall(pattern, content, re.M)]
class AirHPhone(object):
def name(self):
return 'airhphone'
def url(self):
return 'http://www.willcom-inc.com/ja/service/contents_service/create/center_info/index.html'
def run(self):
content = urllib.urlopen(self.url()).read()
n = self.name()
pattern = '<td align="center" bgcolor="white"><font size="2">(\d+\.\d+\.\d+¥.\d+/\d+)</font></td>'
return [(ip, n) for ip in re.findall(pattern, content, re.M)]
class Emobile(object):
def name(self):
return 'emobile'
def url(self):
return 'http://developer.emnet.ne.jp/ipaddress.html'
def run(self):
content = urllib.urlopen(self.url()).read()
n = self.name()
pattern = r'<div align="center">(\d+\.\d+\.\d+\.\d+/\d+)</div>'
return [(ip, n) for ip in re.findall(pattern, content, re.M)]
def get_cidr():
classes = [Docomo, DocomoSP, Ezweb, Softbank, AirHPhone, Emobile]
sources = []
for carrier in classes:
c = carrier()
r = c.run()
if DEBUG:
print '** %s **' % c.name()
for s in r:
print '"%s"' % s[0]
sources += r
# convert cidr to ipaddress
import socket, struct
pat = '([\d\.]+)/(\d+)'
ranges = []
for s in sources:
[(ip, bit)] = re.findall(pat, s[0], re.M)
ipnum = struct.unpack('>L', socket.inet_aton(ip))[0]
mask_ed = (1L << (32 - int(bit))) - 1
mask_st = ~mask_ed
ip_st = ipnum & mask_st
ip_ed = ip_st | mask_ed
ranges.append((ip_st, ip_ed, s[1]))
# sort
ranges.sort()
# merge adjacent range
preip_st = 0
preip_ed = 0
precarr = ''
merge_st = False
mranges = []
i = 0
while True:
st = i
try:
n = ranges[i + 1]
while ranges[i][1] + 1 == n[0] and \
ranges[i][2] == n[2]:
i += 1
n = ranges[i + 1]
mranges.append((ranges[st][0], ranges[i][1], ranges[st][2]))
i += 1
except IndexError, e:
mranges.append((ranges[st][0], ranges[i][1], ranges[st][2]))
break
now = datetime.today()
# output php source
print """<?php
/*
This script is generated by scrape.py at %s.
http://svn.coderepos.org/share/lang/python/cidr-mobilejp/trunk/scrape.py
*/
function ip2mobile($ip) {
$n = sprintf('%%u', ip2long($ip));
""" % now.strftime('%Y-%m-%d %H:%M:%S')
output_php(mranges, 0, len(mranges) - 1, 2)
print """ return 'pc';
}
?>
"""
def output_php(range, st, ed, ind):
# print st, ed, "¥n"
if st > ed:
return
if st == ed:
print ' ' * ind + 'if ($n >= %d && $n <= %d) {' % (
range[st][0], range[st][1])
print ' ' * ind + " return '%s';" % range[st][2]
print ' ' * ind + '}'
return
b = int((st + ed) / 2)
print ' ' * ind + 'if ($n < %d) {' % range[b][0]
output_php(range, st, b - 1, ind + 2)
print ' ' * ind + '} else if ($n <= %d) {' % range[b][1]
print ' ' * ind + " return '%s';" % range[b][2]
print ' ' * ind + '} else {'
output_php(range, b + 1, ed, ind + 2)
print ' ' * ind + '}'
if __name__ == '__main__':
get_cidr()Python を触ったのは初めてなので、おかしいところがあれば修正して下さい(^^ゞ
あと、上記とは別で PHP の配列に入れたランダムな IP を検索するときは、array_search ではなく 連想配列に入れて、isset で検索した方がかなり高速です。array_seach だと全件検索になりますが、isset だとハッシュが使えるので、その分高速です。
ソースコードを下記に貼り付けていますので必要な方はどうぞ〜 (http://www.sugitaku.net/wp-content/uploads/2012/04/ip2mobile.zip)
【追記5/12】github にソースを追加しましたので、必要な方はどうぞ〜 (https://github.com/Sugitaku/ip2mobile)