wikipedia上对于geolocation的解释是这样的:
Geolocation is the identification of the real-world geographic location of an Internet-connected computer, mobile device, website visitor or other.
检测的方法貌似也有很多:
Geolocation can be performed by associating a geographic location with the Internet Protocol (IP) address, MAC address, RFID, hardware embedded article/production number, embedded software number (such as UUID, Exif/IPTC/XMP or modern steganography), invoice, Wi-Fi connection location, or device GPS coordinates, or other, perhaps self-disclosed information.
(班门弄斧一下先,呵呵呵呵) ruby里面取到geo信息的一个相对方便的办法是使用rubygem geoip,虽然本质上还是使用maxmind的data,但是免去了编译和安装其c library的麻烦。 安装gem并下载其depend到的geoip database: [cc lang=”bash”] $ sudo gem install geoip [/cc] [cc lang=”bash” nowrap=”false”] $ wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz && gunzip GeoIP.dat.gz [/cc] 如果想要城市信息,还可以下载稍微大一点的带city info的free database: [cc lang=”bash” nowrap=”false”] $ wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz && gunzip GeoLiteCity.dat.gz [/cc] 简单的测试一下: [cc lang=”ruby”] require ‘rubygems’ require ‘geoip’ p GeoIP.new(‘GeoIP.dat’).country(“google.com”) p GeoIP.new(‘GeoLiteCity.dat’).city(“baidu.com”) [/cc] alright, looks good: [cc lang=”bash”] [“google.com”, “66.249.91.104”, 225, “US”, “USA”, “United States”, “NA”] [“baidu.com”, “220.181.6.81”, “CN”, “CHN”, “China”, “AS”, “22”, “Beijing”, “”, 39.9289, 116.3883] [/cc] 由于geo的普遍性,把其做成可以plug&play的Rack middleware绝对是个好主意,这就是接下来要介绍的Rack::GeoIPCountry,CodeRack Contest的first place。 其原理就是调用geoip gem获得访问IP的geo信息并写入request header,这样后面的app或者middleware就能读到并处理了。 同样写个简单的middleware测试一下: [cc lang=”ruby” lines=”-1”] require ‘geo_ip_country’ class GeoTest def initialize(app) @app = app end def call(env) puts “Remote Address: #{env[‘REMOTE_ADDR’]}” puts “GeoIP Country ID: #{env[‘X_GEOIP_COUNTRY_ID’]}” puts “GeoIP Country Code: #{env[‘X_GEOIP_COUNTRY_CODE’]}” puts “GeoIP Country Code3: #{env[‘X_GEOIP_COUNTRY_CODE3’]}” puts “GeoIP Country: #{env[‘X_GEOIP_COUNTRY’]}” puts “GeoIP Continent: #{env[‘X_GEOIP_CONTINENT’]}” @app.call(env) end end use Rack::ContentLength use Rack::GeoIPCountry use GeoTest run Proc.new { |env| [200, { ‘Content-Type’ => ‘text/html’ }, ‘OK’] } [/cc] rackup起来后,访问http://localhost:9292,确认console下输出了我们想要的geo信息: [cc lang=”bash”] Remote Address: 127.0.0.1 GeoIP Country ID: 0 GeoIP Country Code: – GeoIP Country Code3: – GeoIP Country: N/A GeoIP Continent: – 127.0.0.1 - - [25/Feb/2010 16:36:11] “GET / HTTP/1.1” 200 2 0.0016 [/cc] 当然上面的127.0.0.1是不会有任何信息的,local network也是不会在database里面找到对应的,只有当真正的外网ip hit到我们的server时,我们才能看到有意义的geo信息。