Пользователь
0,0
рейтинг
27 июня 2012 в 07:33

Разработка → Sypex Geo — быстрое определение города по IP

В начале года я публиковал статью Определение страны по IP: тестируем скорость алгоритмов, в которой упоминался мой «велосипед» отличающийся высокой скоростью работы. Одним из популярных вопросов стала возможность определения города по IP.

И вот несколько месяцев спустя, проект начинавшийся, как «for fun» перерос в самостоятельный проект.
Открыт отдельный сайт посвященный проекту Sypex Geo, на котором можно скачать свежие версии API и баз данных, а также ознакомиться с документацией.

Для желающих скорее протестировать правильность определения города по IP — вот ссылка на демо-страницу. А под хабракатом, я опишу некоторые технические подробности и приведу результаты небольшого тестирования.

Формат Sypex Geo 2.1


С момента публикации последней статьи, формат Sypex Geo (сокращенно SxGeo) был оптимизирован, а также добавлена возможность включения в БД двух справочников — городов и регионов.

При создании нового формата, ставились следующие приоритеты:
  • высокая скорость
  • низкое потребление ресурсов
  • открытость (спецификации формата бинарного файла БД и API открыты)
  • универсальность (возможность создания баз данных с любыми наборами данных)

Формат позволяет хранить данные в разной кодировке. После выхода из беты, будут опубликованы скрипты для конвертирования базы данных из MySQL в бинарный файл БД.

В БД хранится следующая информация:
  • ID страны
  • Код страны ISO 3166-1 (двухсимвольный)
  • Код региона FIPS 10-4 (двухсимвольный)
  • Название региона (опционально)
  • Город
  • Широта
  • Долгота
  • Timezone (опционально)

Этот список может быть изменен и/или расширен при необходимости. Более подробную информацию о формате SxGeo 2.1 можно найти на сайте.

Собственная база данных


После весьма близкого знакомства с популярной системой геолокации GeoLite City от MaxMind, было принято решение о создании собственной базы данных. Проблема заключается в том, что в GeoLite City очень много неточностей, мусора, городов дубликатов, излишнего дробления диапазонов, а также проблем с городами бывшего СССР (например, вместо городов взяты названия фирм или имена ответственных из Whois).

В данный момент база основана на GeoLite City, но уже содержит полностью переработанное покрытие России, Украины и Беларуси. Постепенно будут уточняться другие страны, в первую очередь СНГ и Европа. База данных Sypex Geo City содержит названия городов и регионов на русском языке в UTF-8 (встречаются еще не переведенные названия), а также timezone.

Кроме того на сайте доступны другие базы данных преобразованные в формат SxGeo 2.1.

Использование


Использование Sypex Geo API максимально упрощено.
1. Скопировать SxGeo.php и SxGeoCity.dat (или другие базы) на сервер
2. Подключить файл SxGeo.php в свой скрипт, добавив строку

include("SxGeo.php");

3. Создать объект SxGeo

//$SxGeo = new SxGeo(); // Режим по умолчанию, файл бд SxGeo.dat
$SxGeo = new SxGeo('SxGeoCity.dat', SXGEO_BATCH | SXGEO_MEMORY); // Самый быстрый режим

4. Определяем город (SxGeo City, GeoLite City, IpGeoBase)

$SxGeo->get($ip); (возвращает информацию о городе, без названия региона и временной зоны)
// $SxGeo->getCityFull($ip); (возвращает полную информацию о городе и регионе)

Тестирование производительности


И на десерт, небольшое сравнительное тестирование производительности. В качестве оппонентов выступают GeoLite API и Geobaza API. Все участники тестирования используют бинарную базу данных собственного формата, и используют API на PHP. Тестирование проходит под Win 7 (на Linux пропорции сохраняются), PHP 5.2.17.

Результаты после 10 прогонов для каждого API в двух режимах (обычном и с кэшированием в памяти) усреднения и округления до десятков. Для каждого прогона создается массив из 50 000 случайных IP адресов, и в цикле осуществляется поиск каждым алгоритмом.


Предложение и пожелание приветствуются. Также ищутся желающие помочь с портированием API на другие языки, и созданием модулей для Apache и nginx.
@zapimir
карма
99,2
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (84)

  • 0
    Город по IP вычислен правильно (Николаев, Украина), но…

    Timezone: Europe/Zaporozhye

    Это как? Что-то я не слышал про Запорожский часовой пояс :)
    • +4
    • +2
      Тем не менее, такой есть, к примеру вот в доках по PHP. Вполне возможно, что когда-то запорожское время не совпадало с киевским временем.
      У самого был соблазн поубирать к примеру для Украины все, кроме киевского времени, но потом решил оставить так, как пишут в различных справочниках.
      • 0
        Крымское время как-то не совпадало. А запорожское — никогда :)

        • +1
          Ну это уже больше вопрос к создателям этих самых timezone :)
    • 0
      Это вы просто Ubuntu не ставили в украинскую временную зону.
      Нужно хорошо пощелкать мышкой в районе Украины, что бы Запорожье сменилось на Киев.
  • 0
    Город по IP вычислен неправильно. Это, пожалуй, классика жанра, что Сургут (static ip, через Уралсвязьинформ) в 90% баз определяется как Ханты-Мансийск или как Курган, но ни в коем случае не Сургут :) Встречал базы, где это разделение четкое и особенности УСИ предусмотрены.
    • 0
      Если можно IP скиньте в личку поправим.
      • 0
        Скинул, но мой IP такой не один. Проблема намного глобальнее.
      • 0
        Не знаю, реально ли поправить, но Украинский провайдер 3G интернета Intertelecom выдает динамические IP адреса, и все они определяются как в Одессе, хотя физически я нахожусь в Киевской области. Это можно поправить? Любые сервисы определяют так.
        • 0
          Никак это нельзя поправить. Сегодня этот IP в одном городе, а завтра в другом. Пишется место где он зарегистрирован.
    • +1
      да там таких примеров полно — несколько провайдеров работают по всей Сибири. Я думаю что в европейской части тоже должны быть неверные блоки от федералов
      • 0
        Да, у меня проводной Билайн одно время частенько определялся как московский, хотя пользовался я им в Питере.
  • +2
    Пока переходил с 2.0.0 на новую версию, обнаружил, что константа SXGEO_FILE не определена, а в документации написано «Второй параметр — режим работы: SXGEO_FILE (работа с файлом базы, режим по умолчанию)». И метода getCountry($ip) не существует, хотя в док. он есть: "$country = $SxGeo->getCountry($ip); (возвращает двухзначный ISO-код страны)". Кстати, я не нашел в классе ни одной функции, определяющей только страну (get_cc() в пред. версии). Документация тут: sypexgeo.net/ru/docs/
    • 0
      Спасибо за замечание, почему-то API не последней редакции залито было, сейчас обновил файл, там SXGEO_FILE вернулось, да и его можно пропускать.
      Страну возвращают $SxGeo->getCountry($ip) или просто $SxGeo->get($ip)
  • 0
    Промахнулось, примерно на 2500 км. Туннелей нет, если что.
    • 0
      Если можно IP скиньте в личку поправим.
      • 0
        Сейчас пытаюсь выяснить, похоже что всё таки меня здесь развернули через прозрачный прокси, так что возможно и погорячился.
  • +2
    Зашёл из Томска:

    image

    Город определился почти верно, к нему претензий нет: в конце концов, такие записи почти во всех базах RIPE. Но почему на карте Украина? :-)
    • 0
      Там тоже Северск есть, тут скорее всего вопрос как ищется место на карте и как определяются координаты.
      • +1
        Да, похоже, Вы правы. Тут явно речь идёт о Северске донецкой области, даже координаты совпадают.

        Что, однако, не отменяет моего подозрения об ошибке в базе, а наоборот, усиливает.
        • 0
          Проверим, бывают просто ошибки, код страны один, а в адресе город и страна другие.
  • 0
    Кстати, к городам из США неплохо было бы прилепить двухбуквенный код штата, в котором они находятся. Иначе город Cambridge, например, в штате Massachusetts ничем не будет отличаться от одноименного города в шт. Maryland или Vermont. Поля lon-lat могут помочь только на карте.
    • 0
      Так штат должен в регионе показываться. Код есть, так же как и FIPS коды областей.
  • +2
    Сейчас в проектах использую MaxMind, платно, но зато базы постоянно обновляются и вообще, находятся в достаточно актуальном состоянии.
    Как правило, все открытые проекты грешат низкой скоростью обновления и постоянными огрехами. В свое время именно поэтому в свое время отказался от ipgeobase.
    Как будет обстоять с этим вопросом в SypexGeo?
    • 0
      Все подобные проекты обречены на огрехи. Причина очень проста — БД строится по информации из RIR (RIPE, ARIN и т.д.). Т.е. по сети определяется владелец, по владельцу определяется местоположение. У самого же объекта network нету поля «город». Вот и получается, что если провайдер предоставляет услуги в нескольких городах/регионах, то все его сети числятся за «домашним городом».

      Как-то так в первом приближении. Возможно автор меня поправит.
      • 0
        А бывает такое что в «домашнем городе» провайдер вообще не предоставляет услуги?
        • 0
          Я думаю чисто принципиально такое возможно, но вряд ли часто встречается.
      • 0
        Вопрос не в огрехах (понятно, что без этого обойтись не получится), а в скорости их исправления.
        • 0
          Скорость исправления, в данном случае, зависит не только от доброй воли автора проект (исправления ручные), но и от доброй воли провайдеров (только они знают в каком городе какие их сети). Провайдерам, как вы сами понимаете, глубоко чихать на подобные сервисы.
    • 0
      В планах как раз обновляться с частотой MaxMind, для начала просто нужно подчистим базу. Ну и учитывая открытость самого формата в него можно будет конвертировать самостоятельно.

      А сколько кстати размер бинарной базы у платного GeoIP, и как она обновляется полностью файл качается или только разница?
      • 0
        Вообще, если аккумулировать в единое целое информацию из нескольких баз, может получится и интересный вариант.

        Насчет размера не знаю, я пользуюсь запросами к базе через API
  • НЛО прилетело и опубликовало эту надпись здесь
    • +4
      не всегда разрешено, а если разрешено, не всегда отдает. не всегда на том конце современный браузер, да и браузер то не всегда. Да и другого конца может и не быть — просто список адресов, и все
  • 0
    Собственно так и не увидел сравнение с правильно настроенным запросом в базу mysql. В комментах к первой статье несколько раз писали что и сравнение надо делать по одному полю и индекс правильно настроить. Могу лишь добавить что если пошаманить с буферами, то скорость будет в миллионы запросов в секунду

    Есть суровое подозрение что самописный поиск при прочих равных не сможет реально дать большую скорость чем поиск по хешированному индексу, весь вопрос в том сколько ему дали памяти
    • 0
      Прежде чем подозревать, проведите тесты сами. Это не так сложно.
      Или, в крайнем случае, разберитесь в алгоритмах. Благо они не такие большие.
      • +1
        Во-во, хеш дает O(1) а поиск O(logn(n)) в лучшем случае :)
    • 0
      Я как раз собираюсь написать еще одну статью с подробным тестированием, в том числе разных вариантов MySQL запросов. Можете прислать свой вариант правильного запроса к MySQL, я его протестирую.
  • +1
    Может это уже слишком, и я не знаю есть ли это в других базах, но был бы полезным столбец с основными языками, используемыми в стране.
    • 0
      Это в принципе легко добавить. Сейчас собирается подробная инфа по городам (индексы, телефонные коды, численность населения) можно и языки добавить
  • 0
    Жаль IPv6 нет.
    • 0
      Ну не всё сразу, постепенно будем расширяться :)
  • 0
    85.15.175.10 Координаты: 56.8333, 60.6
    Город: Екатеринбург,
    Регион: Свердловская область,

    Из Тюмени зашел через университетский wi-fi (канал предоставлен Екб-м провайдером, правильно)

    зы: (через свой инет все правильно определяет)
    • 0
      Видимо wifi в ТюмГУ ;)
      У меня ip 85.15.175.253, тоже показывает, что г.Екатеринбург, но я так же зашел из г.Тюмень.
  • +3
    Как уже сказал MechanisM выше, хотелось бы IPv6, чтобы было инновационнее, чем у других. Правда туннельные брокеры «сломают» правильность определения местоположения.
    Если верить местным (омским) представителям провайдера Билайн, то пул IP-адресов для домашнего интернета един на всю страну, поэтому сидя в одном и том же городе, разрывая сессию можно добиться местоположения и Смоленск, и Волгоград.
    • +1
      Благодаря туннельным брокерам наконец то будет искоренена проблема ip дискриминации
  • 0
    Город определил правильно — Пенза, но часовой пояс почему-то Самары.
    • 0
      А рабочий IP — 79.133.89.XXX определил в Москве. На самом деле опять же Пенза.
  • +1
    Украинское ОГО! (Укртелеком) похоже определяет как Киев.

    Например, 95.135.190.8 — Здолбунов, ровенская область.
    • 0
      И это не удивительно, определяет так же как и все другие подобные сервисы определения города.
      Вряд ли это возможно исправить без договорённости с Укртелекомом
      (чтобы знать в каком городе из какого диапазона выделяются ip).
      • –2
        Вы хотите чтобы провайдер просто так, по запросу неизвестной частной фирмы, раскрыл адрес своего клиента?
    • 0
      Ну с крупными провайдерами, точности добиться сложно, так как они зачастую тасуют IP как угодно.
  • 0
    2.92.139.74 ростов билайн провод
    определяет как москва
    • 0
      С Билайном проблематично, еще ни разу у меня верно ip не был определен. Подозреваю, что у них общий пул на всю Россию, что было подтверждено комментарием выше.
  • +2
    Данные по России более свежие и актуальные у ipgeobase, причем делается на базе RIPN и обновляется ежедневно.
  • 0
    Огромное спасибо за проект (и вообще, пользуясь случаем, за все sypex*), очень пригодится.
    Одна маленькая идея, родилась после прочтения комментариев к топику — вы бы добавили кнопочку «Город определен неверно, правильный город ...», тогда бы после публикации имели список диапазонов, по которым определение идет неверно.
    • 0
      Спасибо, обязательно добавим кнопочку.
      Кстати под брендом Sypex готовится еще 2 проекта :)
  • 0
    Нахожусь в Смоленске, но сервис утверждает, что в Перми.
  • –4
    Никто еще в комментариях не запостил картинку «Как вычислить по IP… for dummies»? Я удивлен.
  • 0
    Для американского IP показывает русское название штата и города. Мне кажется это неправильный подход.
    • 0
      Если Вы используете базу Sypex Geo City которая должна быть на русском языке, то вполне логично, что названия иностранных городов в ней будут на русском.

      Если Вам нужны названия мест на английском, то используте базу GeoLite City.
      • 0
        Я использовал демо страничку. Наверное будет логично иметь версии на двух разных языках.
    • 0
      Это пока в бете идет уточнение базы, нужно чтобы просто параллельно собиралась обратная связь, от потенциальных пользователей. Все данные сейчас собираются на русском и английском, в дальнейшем будут версии Sypex Geo City на двух языках.
      • 0
        Простите, я так и не нашел на сайте кнопочку «Город определен не верно»
  • 0
    > Для системы статистики нашей Sypex CMS…
    Нагуглил вот это: sypex.net/ru/cms/, но там нет никакого описания. Не собираетесь ли рассказать об этой системе на хабре или у себя на сайте?
  • +1
    Нахожусь в Нью-Йорке, провайдер Time Warner Cable. Определило с точностью до континента)

    • 0
      Данные по штатам по сути, такие же как в Geo Lite City, сейчас работаем в первую очередь над СНГ и Европой.
  • 0
    Документацию бы чуточку подробнее.
    • 0
      Документации по использованию и о самом формате?
      • 0
        Например, чтобы узнать имена ключей выходного массива, пришлось его сперва целиком выводить)
  • 0
    Недавно зашел на яндекс-карты, так они не просто мой город определили, а даже дом на карте указали. Вот как так они делают?
  • 0
    IP сотовых операторов определяет часто неверно. Для Восточной Сибири у МТС (да и у других операторов наверняка тоже) часто показывает как Хабаровск.
    Еще есть отдельная проблема с Opera mini.
  • 0
    Попробовал 2 адреса. Один — Центральный телеграф в Красногорске, определился как Москва, в общем-то ладно, довольно близко. Второй — ТВТ в Набережных Челнах, определился как Казань. Да еще и time zone Europe/Samara. Судя по описанию, Europe/Samara только в Самарской области и Удмуртии, а Казань — Татарстан, там Europe/Moscow.
  • 0
    178.137.20.* пишет Украина \ Киев
    я в Украина \ Донецкая обл \ Макеевка
  • 0
    2.92.91.xx — пишет, что Брянск, хотя на самом деле я из Саратова.
    Но пользуюсь домашним интернетом от билайн, их IP очень редко правильно распознаются.
  • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Будут ли обновления базы по адресам?
    • 0
      Да, как раз вчера обновились.
      • 0
        Супер, спасибо. Проверил адреса, которые раньше не определялись, теперь все ОК.
  • 0
    Внедрен на проекте в 200к+ визитов в сутки. Полет отличный.
  • 0
    а что с модулем для nginx? есть какие-нибудь движения в эту сторону?
  • 0
    В демке json отдается без экранирования апострофов, что приводит к ошибки парсинга.
  • 0
    Увы… но мой город тоже не определился правильно… при том что в самой базе название моего города есть…

    image
    • 0
      А какой IP (можно в личку)? Проверим.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.