Projekt eStats
Darmowe statystyki odwiedzin
Geolokalizacja
Z tego artykułu dowiesz się jak działa geolokalizacja oraz co zrobić aby dodać jej obsługę bez instalowania rozszerzenia dla PHP.
Spis treści
^ Wprowadzenie
Obsługa geolokalizacji jest nowością wprowadzoną w eStats 4.9. Domyślnie używa bazy danych za pośrednictwem rozszerzenia dla PHP pod nazwą geoip. Jednak nawet jeśli nie posiadasz i nie możesz doinstalować tego rozszerzenia na swoim serwerze, to nic straconego, w dalszej części artykułu opisana jest alternatywna metoda dodania obsługi geolokalizacji.
^ Budowa
Biblioteka lib/geoip.php wykorzystuje funkcję geoip_record_by_name () w celu pobrania danych dla podanego adresu IP.
Biblioteka ta deklaruje poniższy zestaw funkcji:
- e_geo_info_available () - zwraca logiczną prawdę, gdy geolokalizacja jest dostępna, w przeciwnym wypadku zwraca fałsz;
- e_geo_init () - inicjalizuje działanie modułu (jednorazowe wczytywanie danych pomocniczych);
- e_geo_info (STRING adres_ip) - zwraca tablicę danych geolokalizacyjnych dla podanego adresu IP lub 0city - miasto, region - identyfikator regionu, country - identyfikator kraju, continent - identyfikator kontynentu, latitude oraz longitude - szerokość i długość geograficzną położenia;
- e_coordinates (FLOAT szerokość_geograficzna, FLOAT długość_geograficzna) - zwraca obrobiony ciąg tekstowy z reprezentacją podanych współrzędnych;
^ Alternatywa
W przypadku braku rozszerzenia na serwerze można posiłkować się wygenerowaną bazą SQLite, o podanej strukturze:
1 2
CREATE TABLE "blocks" ("ipstart" INTEGER, "ipend" INTEGER, "location" INTEGER, PRIMARY KEY ("ipstart", "ipend", "location"));
CREATE TABLE "locations" ("location" INTEGER PRIMARY KEY, "city" TEXT, "region" TEXT, "country_code" TEXT, "latitude" FLOAT, "longitude" FLOAT);
Gdy dostępna jest baza, a nie istnieje funkcja geoip_record_by_name (), to jest definiowana przez bibliotekę.
Bazę danych można wygenerować z użyciem skryptu napisanego w Pythonie. Potrzebne są do tego celu pliki CDV ze strony GeoLite City (GeoLiteCity-Blocks.csv oraz GeoLiteCity-Location.csv) oraz oczywiście interpreter tego języka. Skrypt należy uruchomić wewnątrz katalogu, do którego wypakowaliśmy wyżej wymienione pliki. Po wygenerowaniu bazy należy przenieść plik wynikowy (geoip.sqlite) do katalogu danych (domyślnie data/) i nazwać go geoip_$DBID.sqlite, gdzie $DBID ma wartość, którą możemy znaleźć w pliku conf/config.php. Wygenerowanie bazy danych o rozmiarze 267 MB z 97 MB danych wejściowych zajęło skryptowi 7 minut.
Kod skryptu:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
#!/usr/bin/env python
import csv, sqlite
print 'A Python script for converting MaxMind free geoip CSV files (named GeoLiteCity-Blocks.csv and GeoLiteCity-Location.csv, from http://www.maxmind.com/app/geolitecity) from current directory into SQLite2 database for eStats >= 4.9.'
print '(c) 2007 Emdek, license: GPL.'
print ''
print 'Enter 1 to start converting or 0 to exit:'
Option = raw_input()
if int(Option)==0:
print 'Aborting...'
exit()
Exists = 1
try:
File = open('geoip.sqlite')
File.close()
except:
Exists = 0
Connection = sqlite.connect('geoip.sqlite')
Cursor = Connection.cursor()
if Exists==0:
Cursor.execute('CREATE TABLE "blocks" ("ipstart" INTEGER, "ipend" INTEGER, "location" INTEGER, PRIMARY KEY ("ipstart", "ipend", "location")); CREATE TABLE "locations" ("location" INTEGER PRIMARY KEY, "city" TEXT, "region" TEXT, "country_code" TEXT, "latitude" FLOAT, "longitude" FLOAT);')
print 'Database tables created...'
else:
print 'Using existing database...'
try:
File = open('GeoLiteCity-Blocks.csv', 'rb')
except:
print 'Can not open file "GeoLiteCity-Blocks.csv"!';
exit()
CSVFile = csv.reader(File)
i = 0
for CSVLine in CSVFile:
i += 1
if i < 3:
continue
try:
Cursor.execute('INSERT INTO "blocks" VALUES (%d, %d, %d)', (int(CSVLine[0]), int(CSVLine[1]), int(CSVLine[2])))
except:
print 'An error occured during insertion of row into database!'
print i,' rows inserted into table "blocks"...'
File.close()
try:
File = open('GeoLiteCity-Location.csv', 'rb')
except:
print 'Can not open file "GeoLiteCity-Location.csv"!';
exit()
CSVFile = csv.reader(File)
i = 0
for CSVLine in CSVFile:
i += 1
if i < 3:
continue
try:
Cursor.execute('INSERT INTO "locations" VALUES (%d, %s, %s, %s, %f, %f)', (int(CSVLine[0]), str(CSVLine[3]), str(CSVLine[2]), str(CSVLine[1]), float(CSVLine[5]), float(CSVLine[6])))
except:
print 'An error occured during insertion of row into database!'
print i,' rows inserted into table "locations"...'
File.close()
try:
Connection.commit()
print 'Database saved successful.'
except:
print 'An error occured during saving database file!'
print ''
print 'Copy generated file (geoip.sqlite) into Your $DataDir directory as geoip_$DBID.sqlite.'
Ostatnia modyfikacja: 2008-02-18 15:00:11 CET
Fryderyk EngelsWobec despoty wszyscy są równi, mianowicie - równi zeru.