IP アドレスから携帯キャリアを判別する。

127.0.0.1 のようなドット表記の IP アドレスから、携帯キャリアを判別する関数を生成します。


検索部分は http://d.hatena.ne.jp/tasukuchan/20071231/1199105717 を参考にしました。


異なる部分として

  • 全部 PHP
  • IP アドレスは手動設定。
    • フルブラウザの IP アドレスなどは除外したかった。
    • クローラ作るのも面倒だし、いっそ手動ということで。
  • コードサイズの圧縮。相当小さくなります。
    • else がありません。 if と elseif だけ。
  • 32bit と 64bit を分けた。
    • 必ず int で比較するようにする為。
    • 当然、32/64bit 間で互換性はなし。それぞれ別個に生成すること。
    • →やっぱり止めた。


重要部分の抜粋。

<?php

$imode = array(
'124.146.174.0/24',
'124.146.175.0/24',
'210.136.161.0/24',
'210.153.84.0/24',
'210.153.86.0/24');

$ezweb = array( /* 省略 */ );
$yahoo = array( /* 省略 */ );
$crawlers = array( /* 省略 */ );

// キーがそのまま返り値になる。
$map = array(
    1 => $imode,
    2 => $ezweb,
    3 => $yahoo,
    4 => $crawlers);
// 返り値に文字列を使いたい場合、
// $map = array("'imode'" => $imode);
// のようにする。

生成物。

<?php
function mobile_ip2carrier($v){$n=ip2long($v);if(!defined('PHP_INT_SIZE')||PHP_INT_SIZE!==8)$n=(float)sprintf('%u',$n);if($n<2085863194){if($n<1989727936){if($n<1123631104){if($n<1009460477){if($n>=998712960&&$n<=998713087)return 2;}elseif($n<=1009460477)return 4;elseif($n>=1031078144&&($n<=1031078159||$n>=1031078432&&$n<=1031078447))return 2;}elseif($n<=1123635199)return 4;elseif($n<1867943552){if($n<1208928000){}elseif($n<=1208928127)return 4;elseif($n>=1867943232&&$n<=1867943487)return 2;}elseif($n<=1867943743||$n>=1867943872&&($n<=1867943935||$n>=1867944704&&$n<=1867944959))return 2;}elseif($n<=1989727999)return 2;elseif($n<2037375904){if($n<1990165760){if($n>=1990165248&&($n<=1990165375||$n>=1990165664&&$n<=1990165695))return 2;}elseif($n<=1990165887||$n>=1990165952&&($n<=1990166015||$n>=2037375744&&$n<=2037375871))return 2;}elseif($n<=2037375935)return 2;elseif($n<2085855122){if($n<2037376768){}elseif($n<=2037376895)return 2;elseif($n>=2070736128&&$n<=2070736159)return 3;}elseif($n<=2085855161||$n>=2085855200&&($n<=2085855223||$n>=2085863176&&$n<=2085863177))return 4;}elseif($n<=2085863197)return 4;elseif($n<3533263872){if($n<3412655616){if($n<3404050432){if($n<2089987584){}elseif($n<=2089988095)return 1;elseif($n>=3403013473&&$n<=3403013473)return 4;}elseif($n<=3404051199)return 1;elseif($n<3404621694){}elseif($n<=3404621694)return 4;elseif($n>=3405603040&&$n<=3405603071)return 3;}elseif($n<=3412655871)return 4;elseif($n<3512069632){if($n>=3414423552&&($n<=3414425599||$n>=3419996016&&$n<=3419996021))return 4;}elseif($n<=3512069759)return 4;elseif($n<3532169472){}elseif($n<=3532169727)return 1;elseif($n>=3532785600&&$n<=3532785663)return 3;}elseif($n<=3533264127)return 1;elseif($n<3681328640){if($n<3538321632){if($n<3533264384){}elseif($n<=3533264639)return 1;elseif($n>=3534684544&&$n<=3534684671)return 3;}elseif($n<=3538321647)return 2;elseif($n<3671425024){}elseif($n<=3671429119)return 4;elseif($n>=3681328384&&$n<=3681328511)return 2;}elseif($n<=3681328671)return 2;elseif($n<3682439680){if($n>=3681328680&&($n<=3681328687||$n>=3682439424&&$n<=3682439551))return 2;}elseif($n<=3682439695||$n>=3682440192&&($n<=3682440319||$n>=3724885632&&$n<=3724886015))return 2;return 0;}

利用例。

<?php

$ip = '124.146.174.1'; // i モード
$carrier = '';

switch (mobile_ip2carrier($ip)) {
    case 1: $carrier = 'imode'; break;
    case 2: $carrier = 'ezweb'; break;
    case 3: $carrier = 'yahoo'; break;
    case 4: $carrier = 'crawler'; break;
    default /* case false */: $carrier = 'unknown'; break;
}

echo "$ip: $carrier"; // 124.146.174.1: imode

ソース。

本体
http://xif.jp/php/mobile/ip2carrier.gen.phps

Q. 本当に PHP でやる必要はあるのか?
A. うーん……。


Q. 他に最適化するところあるよね?
A. ううーん……。


まあ、一度作ってしまえば結構便利ですよと。