Search code examples
pythongeopy

Instantiating geopy.geocoders.GoogleV3 with proxies causes exception


I am trying to call GoogleV3 geolocator like this:

geolocator = GoogleV3(proxies={"http": "http://user:password@ip:port"})
address, (latitude, longitude) = geolocator.geocode('address to geocode')

and it raises:

AttributeError: OpenerDirector instance has no __call__ method

What am I doing wrong? How to fix it?


Solution

  • It is not possible in current implementation of GoogleV3 to pass user and password variables directly to urllib2.opener (GoogleV3 uses urllib2 behind the scenes).

    Here is example how urllib2.opener should be called:

    proxy_handler = urllib2.ProxyHandler({'http': 'http://www.example.com:3128/'})
    proxy_auth_handler = urllib2.ProxyBasicAuthHandler()
    proxy_auth_handler.add_password('realm', 'host', 'username', 'password')
    
    opener = urllib2.build_opener(proxy_handler, proxy_auth_handler)
    # This time, rather than install the OpenerDirector, we use it directly:
    opener.open('http://www.example.com/login.html')
    

    Sadly, but current GoogleV3 implementation does not use urllib2.ProxyBasicAuthHandler .

    So, you need to extend it by modifying source: https://github.com/geopy/geopy/blob/master/geopy/geocoders/base.py On the top add:

    from urlparse import urlparse

    then find 'if self.proxies is None:' code and replace it with:

        if self.proxies is None:
            self.urlopen = urllib_urlopen
        else:
            params = urlparse(proxies[1])
            host = params.get('hostname')
            username = params.get('username')
            password = params.get('password')
            if host and username and password:
                proxy_auth_handler = urllib2.ProxyBasicAuthHandler()
                proxy_auth_handler.add_password(None, host, username, password)
                self.urlopen = build_opener(
                   ProxyHandler(self.proxies, proxy_auth_handler),
                )