让urllib2的DNS亦通过Proxy查询

上一篇文章中讲到的方法,在某些时候不好用。比如我在本机调试链接到facebook的程序,开始没有问题,后来突然就不工作了。得到如下提示:

<urlopen error [Errno -2] Name or service not known

经检查发现出现大的问题仍然是DNS解析。而我本机测试twitter没有问题的原因,也是因为其DNS未被污染。开始时Facebook正常估计也是因为凑巧当时其并未受到污染所致。

经过搜索罚下如下方案,经测试工作正常:

http://www.talesofacoldadmin.com/2012/11/13/proxying-dns-with-python.html

 

至此上文提到的解决django-social-auth的补丁,最终应该是:

def dsa_urlopen(*args, **kwargs):
    """Like urllib2.urlopen but sets a timeout defined by
    SOCIAL_AUTH_URLOPEN_TIMEOUT setting if defined (and not already in
    kwargs)."""
    timeout = setting('SOCIAL_AUTH_URLOPEN_TIMEOUT')
    if timeout and 'timeout' not in kwargs:
        kwargs['timeout'] = timeout
    import socks
    import socket

    socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 1080)
    socket.socket = socks.socksocket
    def _create_connection(address, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,source_address=None):
        msg = "getaddrinfo returns an empty list"
        host, port = address
        if len(address) == 2 and isinstance(address,(list,tuple)) and isinstance(address[0],unicode):
            address = (str(address[0]),address[1])
        for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):
            af, socktype, proto, canonname, sa = res
            sock = None
            try:
                sock = socket.socket(af, socktype, proto)
                if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:
                    sock.settimeout(timeout)
                sock.connect(address)
                return sock

            except socket.error, msg:
                if sock is not None:
                    sock.close()

        raise socket.error, msg

    socket.create_connection = _create_connection
    # Magic!
    def getaddrinfo(*args):
        return [(socket.AF_INET, socket.SOCK_STREAM, 6, '', (args[0], args[1]))]
    socket.getaddrinfo = getaddrinfo

    return urlopen(*args, **kwargs)

 

 
posted @ 2012-12-21 09:01  雨吁的嘘  阅读(740)  评论(0编辑  收藏  举报