【问题标题】:How to find location with IP address in Python?如何在 Python 中使用 IP 地址查找位置?
【发布时间】:2014-07-10 13:49:42
【问题描述】:

我正在开发一个项目,该项目需要将用户位置存储在我的数据库中。我得到了该用户的公共 IP 地址。但我无法获取用户位置。我尝试了几种方法(来自 StackOverflow),但没有找到任何提示。像下面这样

url = urllib.urlopen("http://api.hostip.info/get_html.php?ip=%s&position=true" % ip)
data = re.compile('^[^\(]+\(|\)$').sub('', url.read())
print data

但我得到的结果是

Unknown Country?) (XX)
City: (Unknown City?)

另一种方式:

import urllib

response = urllib.urlopen("http://api.hostip.info/get_html.php?ip={}&position=true".format(ip)).read()

print(response)

但结果是

Country: (Unknown Country?) (XX)
City: (Unknown City?)

Latitude: 
Longitude: 
IP: 115.xxx.xxx.xx

任何帮助将不胜感激!

【问题讨论】:

  • 显然hostip.info不知道该IP属于哪个国家。
  • @AnttiHaapala,我也试过ipinfodb.com,但是对于两个不同的IP位置,它给出了相同的地址
  • 在尝试正则表达式提取相关部分之前,print url.read() 是什么?

标签: python


【解决方案1】:

获取IP地址以及详细位置的最简单方法之一是使用http://ipinfo.io

import re
import json
from urllib2 import urlopen

url = 'http://ipinfo.io/json'
response = urlopen(url)
data = json.load(response)

IP=data['ip']
org=data['org']
city = data['city']
country=data['country']
region=data['region']

print 'Your IP detail\n '
print 'IP : {4} \nRegion : {1} \nCountry : {2} \nCity : {3} \nOrg : {0}'.format(org,region,country,city,IP)

【讨论】:

  • 这不是付费服务吗?
  • 事实证明,他们制作了自己的 Python 库! github.com/ipinfo/python 又名pip install ipinfo
  • @AlihaydarGubatov 刚刚创建了一个帐户。每月最多可免费使用 50,000 美元,并且不需要任何付款信息。
【解决方案2】:

试试pygeoip

~$ ping stackoverflow.com
PING stackoverflow.com (198.252.206.16) 56(84) bytes of data.

>>> import pygeoip
>>> GEOIP = pygeoip.GeoIP("/absolute_path/GeoIP.dat", pygeoip.MEMORY_CACHE)
>>> GEOIP.country_name_by_addr(ip)
'United States'

GeoIP.data 可用here

【讨论】:

【解决方案3】:

对于 python-3.x

def ipInfo(addr=''):
    from urllib.request import urlopen
    from json import load
    if addr == '':
        url = 'https://ipinfo.io/json'
    else:
        url = 'https://ipinfo.io/' + addr + '/json'
    res = urlopen(url)
    #response from url(if res==None then check connection)
    data = load(res)
    #will load the json response into data
    for attr in data.keys():
        #will print the data line by line
        print(attr,' '*13+'\t->\t',data[attr])

【讨论】:

  • 像魅力 Python 3.6 64bit 一样工作
【解决方案4】:

感谢所有解决方案和解决方法! 但是,我无法使用上述所有方法。

这对我有用:

import requests

response = requests.get("https://geolocation-db.com/json/39.110.142.79&position=true").json()

这种方法看起来简单易用。 (我需要使用字典响应...)

将来,“geolocation-db.com”可能会变得不可用,因此可能需要其他来源!

【讨论】:

    【解决方案5】:

    假设您已经获得了 ip 地址,您可以尝试使用 IP2Location Python 库来获取用户位置。示例代码如下:

    import os
    import IP2Location
    
    database = IP2Location.IP2Location(os.path.join("data", "IPV4-COUNTRY.BIN"))
    
    rec = database.get_all(ip)
    
    print(rec.country_short)
    print(rec.country_long)
    print(rec.region)
    print(rec.city)
    print(rec.isp)  
    print(rec.latitude)
    print(rec.longitude)            
    print(rec.domain)
    print(rec.zipcode)
    print(rec.timezone)
    print(rec.netspeed)
    print(rec.idd_code)
    print(rec.area_code)
    print(rec.weather_code)
    print(rec.weather_name)
    print(rec.mcc)
    print(rec.mnc)
    print(rec.mobile_brand)
    print(rec.elevation)
    print(rec.usage_type)
    

    取决于你的要求,例如如果你想获取用户的国家名称和地区名称,你可以这样做:

    import os
    import IP2Location
    
    database = IP2Location.IP2Location(os.path.join("data", "IPV4-COUNTRY.BIN"))
    
    rec = database.get_all(ip)
    
    user_country = rec.country_long
    user_region = rec.region
    

    更多详情,您可以访问这里:IP2Location Python library

    Github 链接:IP2Location Python library Github

    【讨论】:

    • 很棒的离线解决方案。
    【解决方案6】:

    您可以使用https://geolocation-db.com的服务,支持IPv4和IPv6。返回 JSON 对象或 JSONP 回调函数。

    Python 2:

    import urllib
    import json
    
    url = "https://geolocation-db.com/json"
    response = urllib.urlopen(url)
    data = json.loads(response.read())
    print data
    

    Python 3:

    import urllib.request
    import json
    
    with urllib.request.urlopen("https://geolocation-db.com/json") as url:
        data = json.loads(url.read().decode())
        print(data)
    

    python 3 jsonp 示例:

    import urllib.request
    import json
    
    with urllib.request.urlopen("https://geolocation-db.com/jsonp/8.8.8.8") as url:
        data = url.read().decode()
        data = data.split("(")[1].strip(")")
        print(data)
    

    【讨论】:

    • 不支持https://geoip-db.com/json/{other IP};所有查询都返回运行脚本的机器的 IP。
    • 确实对 json 正确。但是,https://geoip-db.com/jsonp/ 回调有效。
    【解决方案7】:

    我在自己的服务器上做同样的事情。从http://ipinfodb.com/register.php 获取 API 密钥并尝试:

    import requests
    
    ipdb = "http://api.ipinfodb.com/v3/ip-city/?key=<your api key>&ip="
    ip_address = function_to_get_ip_address()
    location = " ".join(str(requests.get(ipdb+ip_address).text).split(";")[4:7])
    

    location 的值将是COUNTRY REGION CITY

    请记住,IP 地址不是精确的地理定位器。尤其是从移动设备访问您的网站时,您会看到 IP 地址的位置可能距离用户的实际位置 100 英里。

    【讨论】:

      【解决方案8】:

      这最终取决于您如何获取计算机 IP 地址。如果您在 VPN 或其他专用网络上,仅获取本地 IP 地址将不会返回任何内容,就像您现在看到的那样。在这种情况下,您必须像这样获取公共 IP 地址:

      url = 'http://api.hostip.info/get_json.php'
      info = json.loads(urllib.urlopen(url).read())
      ip = info['ip']
      

      这是我获取您正在寻找的所有信息的完整代码(我使用的是 freegeoip.net):

      import urllib
      import json
      
      url = 'http://api.hostip.info/get_json.php'
      info = json.loads(urllib.urlopen(url).read())
      ip = info['ip']
      
      urlFoLaction = "http://www.freegeoip.net/json/{0}".format(ip)
      locationInfo = json.loads(urllib.urlopen(urlFoLaction).read())
      print 'Country: ' + locationInfo['country_name']
      print 'City: ' + locationInfo['city']
      print ''
      print 'Latitude: ' + str(locationInfo['latitude'])
      print 'Longitude: ' + str(locationInfo['longitude'])
      print 'IP: ' + str(locationInfo['ip'])
      

      【讨论】:

      • 我尝试这个例子。但它显示错误
      【解决方案9】:

      要求:

      sudo add-apt-repository ppa:maxmind/ppa
      sudo apt update
      sudo apt install libmaxminddb0 libmaxminddb-dev mmdb-bin
      sudo pip install geoip2
      

      geoip 数据库:

      wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz
      tar xvfz GeoLite2-City.tar.gz
      

      nginx 访问日志示例:

      python -c 'import geoip2.database
      reader = geoip2.database.Reader("./GeoLite2-City/GeoLite2-City.mmdb")
      for line in open("/var/log/nginx/access.log').readlines():
          response = reader.city(line.split(" ")[0])
          print(dir(response))
      '
      

      相关:

      【讨论】:

      • 对我来说,'pip install geoip2' 有效。无需添加 maxmin repo 和 apt-install 库。 (debian-testing 2019 年 2 月)
      【解决方案10】:

      我发现 ipinfo 提供最好的服务,并为每月多达 50k 次调用提供免费 API 使用 - 请参阅“速率限制”here

      import ipinfo
      
      access_token = '123456789abc'
      handler = ipinfo.getHandler(access_token)
      ip_address = '216.239.36.21'
      details = handler.getDetails(ip_address)
      details.city
      'Mountain View'
      details.country
      'US'
      details.loc
      '37.3861,-122.0840'
      

      【讨论】:

        【解决方案11】:

        https://github.com/airakesh/BeautifulSoupRecipes/blob/master/geoip.py

        # Get Geolocation(Country) and hostname by passing a file having a bunch of IP addresses as the argument from the command line. Example- python GeoIP.py path-to-file-containing-IP addresses:
        https://github.com/airakesh/BeautifulSoupRecipes/blob/master/sample_ips.txt
        
        import re
        import os
        import sys
        import subprocess
        import socket
        
        # Input file argument
        ips_file = sys.argv[1]
        
        # The regular expression for validating an IP-address                                                                                                                                                            
        pattern = '''^(25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)'''
        
        def getGeoHost():
            fp = open(ips_file, 'rb')
            for line in fp:
                line = line.strip()
                addr = line.decode('utf-8')
                regex = re.compile(pattern)
                match = regex.match(addr)
                # Get hostname by IP address                                                                                                                                                                          
                try:
                    host = socket.gethostbyaddr(addr)
                    hostname = host[0]
                # Print Unknown no hostname is available                                                                                                                                                                  
                except:
                    hostname = 'Unknown'
        
                # Get geolocation by IP address                                                                                                                                                                            
                get_geo_cmd = 'geoiplookup ' + addr
                geo_str = subprocess.check_output(get_geo_cmd, shell=True)
                geo = geo_str.decode('utf-8')
        
                # Match country name pattern                                                                                                                                                                              
                geo_pattern = '''^(GeoIP Country Edition: ([A-Z]{2})\, (.*))'''
                geo_regex = re.compile(geo_pattern)
                country_match = re.match(geo_pattern, geo)
                # Check country name is available and if not, print 'Unknown'                                                                                                                                               
                if country_match != '' and geo_pattern:
                    try:
                        country = country_match.group(3)
                    except:
                        country = 'Unknown'
                # Clubbing together in format 'IP|Country|Hostname' data                                                                                                                                                    
                geo_hostname = addr + ' | ' + country + ' | ' + hostname
                print geo_hostname
        
        
        if __name__ == "__main__":
        
            ips_detail_list = getGeoHost()
        

        【讨论】:

          【解决方案12】:

          你可以使用 ipinfo 的 api 来做到这一点 首先去ipinfo.io注册。你会得到一个访问令牌,复制它,现在做pip install ipinfo 现在你可以输入这个示例代码:

          >>> import ipinfo
          >>> handler = ipinfo.getHandler(access_token)
          >>> d = handler.getDetails(ip_address)
          >>> d.city
          

          或者,如果您直接执行d.details,它将返回一个字典,您也可以将其用作字典,它将包含所有内容,例如 IP 地址、城市、国家/地区、州等。您也可以使用它们像这样d.country 或位置d.loc,对于城市,正如我所写,d.city

          【讨论】:

            【解决方案13】:
            import urllib.request
            import json
            
            
            ips = ['x.x.x.x', 'x.x.x.x','x.x.x.x']
            
            
            for ip in ips:
                    with urllib.request.urlopen("https://geolocation-db.com/jsonp/"+ip) as url:
                            data = url.read().decode()
                            data = data.split("(")[1].strip(")")
                            print(data)
            
            

            【讨论】:

            • 欢迎来到 Stack Overflow!虽然这段代码可以解决问题,including an explanation 解决问题的方式和原因确实有助于提高帖子的质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提出问题的人。请edit您的答案添加解释并说明适用的限制和假设。
            • 欢迎来到 Stack Overflow!在 Stack Overflow 上,如何 很重要,但网站质量水平的很大一部分来自人们不遗余力地解释为什么这一事实。虽然仅代码的答案可以让提出问题的人克服他们可能面临的任何障碍,但从长远来看,这对他们或未来的访问者没有多大好处。见Is there any benefit in code-only answers?
            • this answer 中已经提到了使用 geolocation-db.com。这只是该答案的副本,仅添加了 for 循环。
            • 是的,答案重复
            【解决方案14】:
            nmap --script ip-geolocation-geoplugin <target>
            
            Script Output
            | ip-geolocation-geoplugin:
            | coordinates: 39.4208984375, -74.497703552246
            |_location: New Jersey, United States
            

            https://nmap.org/nsedoc/scripts/ip-geolocation-geoplugin.html

            【讨论】:

            • 这不是 Python 脚本。
            【解决方案15】:

            您可以为此使用一些 API 服务。

            例如,https://apiip.net,他们的 API 提供了大量关于 IP 的信息

            简单的 GET 调用:

            https://apiip.net/api/check?ip=67.250.186.196&accessKey={your_api_key}
            

            示例代码:

            import json
            import urllib.request
            
            # Define API URL
            API_URL = 'https://apiip.net/api/check?accessKey={YOUR_API_KEY}'
            
            # Enter the ip for search
            IP_FOR_SEARCH = '&ip=67.250.186.196'
            
            # Creating request object to API
            req = urllib.request.Request(API_URL+IP_FOR_SEARCH)
            
            # Getting in response JSON
            response = urllib.request.urlopen(req).read()
            
            # Loading JSON from text to object
            json_response = json.loads(response.decode('utf-8'))
            
            # Print the results
            print(json_response)
            

            【讨论】:

              猜你喜欢
              • 2013-11-15
              • 2018-01-05
              • 2014-07-31
              • 2022-11-05
              • 2011-10-26
              • 1970-01-01
              • 2015-04-28
              • 1970-01-01
              • 2012-01-31
              相关资源
              最近更新 更多