FROM THE OLD SITE

旧WordPressで公開していた記事を、当時の内容を尊重して再掲載しています。

PAST ARTICLE · Program

PHP で IP から各携帯キャリアの判定

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)