`
lovejuan1314
  • 浏览: 342859 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

将geoip,geoip_city数据导入Postgresql数据库

阅读更多
MaxMind公司提供的geoip数据格式有两种,一种是二进制文件,一种是csv文件,可能还有其他格式的,比如dotted octet format。本次总结只以csv文件举例。

1.从MaxMind得到csv文件,这个需要付费的。
2.然后将得到的文件解压缩到服务器特定目录。
3.安装PostgresSQL数据库,并且安装ip4r
  (可以从网上下载postgresql-distrib-ip4r包安装)
4.安装python以及Psycopg2 
   1)yum list "*psycopg*"
   2)或者直接用wget ftp://ftp.muug.mb.ca/mirror/fedora/epel/5/i386/python-psycopg2-2.0.7-1.el5.i386.rpm得到
   3)rpm -Uvh psycopg2-2.0.7-1.el5.i386.rpm
5. 准备python导入脚本文件
'''
Script for loading GeoIP CSV data into a postgresql database
'''

import logging, psycopg2, psycopg2.extensions, sys

from optparse import OptionGroup, OptionParser
from StringIO import StringIO

class GeoIPDataLoader(object):

    def __init__(self, dsn, blocks='GeoLiteCity-Blocks.csv', locations='GeoLiteCity-Location.csv', schema='public'):
        self.con = psycopg2.connect(dsn)
        # We don't need transactions... right?
        self.con.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
        # The data is in ISO8859_15 encoding
        self.con.set_client_encoding('iso8859_15')
        self.cur = self.con.cursor()

        self.blocks_csv = blocks
        self.location_csv = locations
        self.schema = schema
 
    def close(self):
        self.con.close()

    def create_tables(self):
        print 'Creating structure...',
        self.db_execute(
            '''
                CREATE TABLE locations
                (
                  id bigint NOT NULL,
                  country character(2) NOT NULL,
                  region character(2),
                  city character varying(75),
                  postal_code character varying(15),
                  latitude numeric(6,4) NOT NULL,
                  longitude numeric(7,4),
                  metro_code integer,
                  area_code integer,
                  CONSTRAINT locations_pkey PRIMARY KEY (id)
                );
                
                CREATE TABLE blocks
                (
                  start_ip bigint NOT NULL,
                  end_ip bigint NOT NULL,
                  location_id bigint NOT NULL
                );
               
            '''
            )
        print '\033[1;32mDone\033[1;m'
                
    def create_indexes(self, ip4=False):
        print 'Adding Indexes...',
        sys.stdout.flush()
        if not ip4:
            self.db_execute('''
             CREATE INDEX ix_start_end_ip ON blocks 
                USING btree (start_ip, end_ip) WITH (FILLFACTOR=100);
             CREATE INDEX ix_end_start_ip ON blocks 
                USING btree (end_ip, start_ip) WITH (FILLFACTOR=100); 
                ''')
        else:
            self.db_execute('''
                 CREATE INDEX ix_ip_range ON blocks
                   USING gist (ip_range) WITH (FILLFACTOR=100);
                ''')
        print '\033[1;32mDone\033[1;m'
        
    def create_functions(self, ip4=False):
        print 'Adding utility functions...',
        sys.stdout.flush()
        if ip4:
            self.db_execute('''
                CREATE OR REPLACE FUNCTION get_location(inet) RETURNS bigint AS $$
                  SELECT location_id FROM %s.blocks
                  WHERE ip_range >>= ip4($1)
                $$ LANGUAGE SQL;
                ''' % self.schema)
        else:
            self.db_execute('''
                CREATE OR REPLACE FUNCTION inet_to_bigint(inet) RETURNS bigint AS $$
                    SELECT $1 - inet '0.0.0.0'
                $$ LANGUAGE SQL;
                ''' % self.schema)
        print '\033[1;32mDone\033[1;m'
    
    def create_schema(self):
        try:
            self.db_execute('''CREATE SCHEMA %s;''' % self.schema)
        except psycopg2.ProgrammingError:
          pass   

        self.db_execute('SET search_path TO %s,public;' % self.schema)
        
    def db_execute(self, ddl):
        self.cur.execute(ddl)
#        self.con.commit()
    
    def load_data(self):
        # Load Locations
        self.load_table(self.location_csv, 'locations')
        # Load Blocks
        self.load_table(self.blocks_csv, 'blocks')
    
    def load_table(self, file_name, table_name):
        print 'Loading table \033[1;34m%s\033[1;m from file \033[1;34m%s\033[1;m...' % (table_name, file_name),
        sys.stdout.flush()
        geo_file = open(file_name)
        # Skip the copyright header
        geo_file.readline()
        geo_file.readline()
        #Remove quotes... psycopg2's `copy` errors on them
        string_data = geo_file.read().replace('"', '')
        self.cur.copy_from(StringIO(string_data), table_name,  sep=',', null='')
        print '\033[1;32mDone\033[1;m'
    
    def migrate_to_ip4(self):
        print 'Adding ip_range column'        
        self.db_execute('''
                        ALTER TABLE blocks ADD COLUMN ip_range ip4r;
                        ALTER TABLE blocks ALTER COLUMN ip_range SET STORAGE PLAIN;
                        ''')
        
        print 'Migrating data to ip4...',
        sys.stdout.flush()
        self.db_execute('''UPDATE blocks SET ip_range = ip4r(start_ip::ip4, end_ip::ip4)''')
        print '\033[1;32mDone\033[1;m'

        print 'Dropping unneeded columns'
        self.db_execute('''
                        ALTER TABLE blocks DROP COLUMN start_ip;
                        ALTER TABLE blocks DROP COLUMN end_ip;
                        ''')
    def vacuum(self):
        print 'Vaccuming database...',
        sys.stdout.flush()
        self.db_execute('VACUUM FULL ANALYZE')
        print '\033[1;32mDone\033[1;m'

def main():
    DSN = "dbname='%s' user='%s' host='%s'"

    parser = OptionParser()
    # Operational options
    parser.add_option('-c', '--load-ddl', dest='load_ddl', default=False,
                      action='store_true', help='Create database structure')
   
    parser.add_option('-g', '--load-data', dest='load', default=False,
                      action='store_true', help='Load the GeoIP data')

    parser.add_option('-b', '--blocks-file', dest='blocks_csv', default='GeoLiteCity-Blocks.csv',
                      action='store', help='GeoIP Blocks CSV file [default: %default]', metavar='BLOCKS_FILE')
    parser.add_option('-l', '--locations-file', dest='locations_csv', default='GeoLiteCity-Location.csv',
                      action='store', help='GoeIP Locations CSV file [default: %default]', metavar='LOCATIONS_FILE')

    db_group = OptionGroup(parser, 'Database Options')
    # Database options
    db_group.add_option('-H', '--host', dest='db_host', default='localhost',
                      action='store', help='Database host [default: %default]', metavar='DB_HOST')
    db_group.add_option('-d', '--database', dest='db_name', default='geoip_db',
                      action='store', help='Database name [default: %default]', metavar='DATABASE_NAME')
    db_group.add_option('-U', '--user', dest='db_user', default='geoip',
                      action='store', help='User [default: %default]', metavar='USER_NAME')
     db_group.add_option('-W','--prompt',dest='password',default='',
                      action='store',help='Password',metavar='PASSWORD')

    db_group.add_option('-s', '--schema', dest='schema', default='public',
                      action='store', help='Database Schema [default: %default]', metavar='SCHEMA')

    db_group.add_option('--ip4r', dest='ip4', default=False,
                      action='store_true', help='Use IP4r module [default: %default]')

    parser.add_option_group(db_group)
    
    (options, args) = parser.parse_args()

     data_loader = GeoIPDataLoader("dbname='%s' user='%s' password='%s'  host='%s'" % (options.db_name, options.db_user,options.password, options.db_host),
                                  blocks=options.blocks_csv, locations=options.locations_csv, schema=options.schema)

    if not options.load_ddl and not options.load:
        parser.print_help()
        return

    if options.load_ddl:
        if options.schema != 'public':
            data_loader.create_schema()
        data_loader.create_tables()
 
    if options.load:
        data_loader.load_data()

    if options.ip4:
        data_loader.migrate_to_ip4()

    if options.load:
        data_loader.create_indexes(options.ip4 is True)

    if options.load_ddl:
        data_loader.create_functions(options.ip4 is True)

    data_loader.vacuum()

if __name__ == "__main__":
    main()



注意:
1.该文件中创建索引使用的WITH选项是PostgresSQL 8.2以上版本才支持的。
2.我添加了数据库密码验证,要不数据库密码验证通不过。

6: 创建表

--DROP TABLE locations;
--DROP TABLE blocks;

-- Table DDL
CREATE TABLE locations
(
  id bigint NOT NULL,
  country character(2) NOT NULL,
  region character(2),
  city character varying(75),
  postal_code character varying(15),
  latitude numeric(6,4) NOT NULL,
  longitude numeric(7,4),
  metro_code integer,
  area_code integer,
  CONSTRAINT locations_pkey PRIMARY KEY (id)
);

CREATE TABLE blocks
(
  start_ip bigint NOT NULL,
  end_ip bigint NOT NULL,
  location_id bigint NOT NULL,
  CONSTRAINT blocks_pkey PRIMARY KEY (start_ip, end_ip)
);


7: 使用脚本命令导入
chmod +x /tmp/load_geoip.py
python /tmp/load_geoip.py --ip4r  -l /tmp/GeoIPCity-134-Location.csv -b /tmp/GeoIPCity-134-Blocks.csv --host 127.0.0.1 -U slony  -W 12345 -d BeboAndFacebook -g


8. 如果是更新的话,要考虑slony集群环境,先用slonik在主数据库服务器上把表清空,然后再导入新的数据。

参考文章:http://www.siafoo.net/article/53
2
0
分享到:
评论

相关推荐

    GeoIP.dat__GeoLitecity.rar

    标题中的"GeoIP.dat__GeoLitecity.rar"和描述中的内容暗示了我们讨论的核心是Nginx的GeoIP模块以及相关的数据库文件。 GeoIP模块是Nginx的一个第三方模块,用于获取访问者IP地址的地理位置信息。这个功能对于网站...

    GeoIP地址库,用于查找对应IP地址对应的国家,城市

    使用GeoIP-1.4.8,开发者需要先将库编译为适合自己操作系统的可执行文件或库,然后在自己的应用程序中调用相应的API,如`GeoIP_open()`来打开数据库,`GeoIP_record_by_name()`或`GeoIP_city_by_ip()`来获取IP地址的...

    ngx_http_geoip2_module:使用ngx_http_geoip2_module编译Nginx 1.15.0并下载GeoIP 2数据库

    此外,该脚本还有助于下载Maxmind GeoIP2国家/地区数据库的免费版本,并将其放置在Nginx文件夹中。 我还包括Nginx配置以及geoblock脚本,您可以从此处开始进行自定义,以自定义解决国家/地区街区功能的需求。安装将...

    geoip2.database包 GeoLite2-City.mmdb

    geoip2 可解析出ip的位置和所在城市等信息,GeoLite2-City.mmdb数据库,仅供学习使用。

    小巧精悍、准确、实用 GeoIP2 数据库

    目前市面上绝大多数的代理工具都依赖于 GeoIP2 数据库判断地址所属地。它们的规则结尾部分一般都会有一条类似 GEOIP, CN,用来查询目的 IP 地址是否属于中国大陆,从而判断是否直连。 这些代理工具通常使用的 GeoIP...

    通过GeoIP获取ip所属地,并将国家转换为中文

    `geoip.inc`是一个PHP库,它包含了读取和查询GeoIP数据库的函数,例如`geoip_country_name_by_addr()`,这个函数可以接收一个IP地址作为参数,返回对应的国家名称。 接下来,`ip_2_country.php`是实现IP到国家信息...

    通过GeoIP获取ip所属地 (国家,城市,时区,邮编,经纬度等)

    4. **获取详细信息**:除了国家代码,还可以获取更详细的信息,如城市名(`geoip_city()`),时区(`geoip_time_zone_by_country_and_city()`),邮政编码(需要高级数据库版本)和经纬度(`geoip_record_by_name()`...

    GeoIP最新数据库(2022-04-19)

    Geo是geographic的缩写,意思是地理的,GeoIP即为IP地理位置数据库,可以根据IP获得地理位置信息。GeoLite2是GeoIP2的免费版本,与GeoIP2数据库相比准确性较差。GeoLite2数据库每周更新国家、城市和自治系统编号信息...

    geoip方法1.zip

    $record = geoip2_city($ip); // 调用GeoIP2的API echo "经度: " . $record->location->longitude . "\n"; echo "纬度: " . $record->location->latitude . "\n"; ?> ``` 这段代码首先引入了`geoip.inc.php`,然后...

    PHP geoIP及例子下载

    此外,为了提高性能,可以使用内存缓存(GEOIP_MEMORY_CACHE)选项,将数据库加载到内存中,避免每次查询时的磁盘I/O操作。 7. **应用场景**:PHP GeoIP扩展常用于网站统计分析、个性化内容推荐、广告定位、内容...

    ELK之GEOIP数据库包

    "GeoLite2-City_20190312"是MaxMind的一个特定版本的GeoLite2城市级GEOIP数据库。GeoLite2是免费的,但功能相对有限,相比于商业版的GeoIP2数据库,它可能不包含最新的IP地址信息或者详细程度较低。不过,对于大多数...

    city.dat geoip 数据库文件

    geoip 数据库文件

    GEOIP库与php版本使用

    所谓GeoIP,就是通过来访者的IP, 定位他的经纬度...$geo=geoip_open('GeoIP.dat',GEOIP_STANDARD); $counrty= geoip_country_code_by_addr($geo, '202.96.128.166'); $counrty=$counrty?strtolower($counrty):'cn';

    GeoIP_1.4.8.tar.gz 地理信息系统,资源包含geoIP_1.4.8的所有资源。

    GeoIP_1.4.8.tar.gz 是一个与地理信息系统相关的压缩包,它包含了用于识别网络IP地址地理位置信息的库和工具。这个版本是1.4.8,可能包括了更新和修复,以提高性能和稳定性。在IT领域,地理信息系统(GIS)是一种...

    最新的geoip库下载(完整版)

    GeoLiteASNum.dat GeoIPASNum.dat ,同时我这里包含了csv格式的城市和地区数据库 目前最新版本更新至2024-03-21 通过这几个库,你可以通过ip地址反查ip所在的国家,地区和街道等信息,适用于根据IP地址获取客户端...

    GeoIP2-Country-CSV_20200331.zip

    Maxmind GeoIP2-Country-CSV_20200331 朋友买的收费库 通过GeoIP获取ip所属地 完整: GeoIP2-Anonymous-IP-CSV_20200428.zip GeoIP2-Anonymous-IP_20200428.tar.gz GeoLite2-ASN-CSV_20200428.zip GeoLite2-...

    GeoLite2-City.mmdb数据库下载

    GeoLite2-City 数据库比 GeoIP2 City 数据库小,并且更新频率较低,但它仍然提供了相当准确的地理位置数据。 文件扩展名 .mmdb 指的是 MaxMind 的新二进制格式,它用于存储 IP 地址到地理位置的映射。与传统的 ...

    Maxmind GeoIP ISP 数据库

    更新到2014-01-23,价值25刀的ISP数据库文件

    Nginx服务器中配置GeoIP模块来拦截指定国家IP

    fastcgi_param GEOIP_CITY_COUNTRY_CODE3 $geoip_city_country_code3; fastcgi_param GEOIP_CITY_COUNTRY_NAME $geoip_city_country_name; fastcgi_param GEOIP_REGION $geoip_region; ``` 通过这种方式,Nginx可以...

    Python-pygeoipMaxmind二进制GeoIP数据库的纯PythonAPI

    GeoIP数据库是一种存储了全球互联网IP地址与其对应地理位置信息的数据文件,常用于网络应用中的地理定位服务。这个API使得Python开发者无需依赖C扩展或外部二进制模块,就能直接在Python环境中高效地访问这些数据。 ...

Global site tag (gtag.js) - Google Analytics