惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
L
LangChain Blog
博客园_首页
J
Java Code Geeks
博客园 - 【当耐特】
Microsoft Azure Blog
Microsoft Azure Blog
小众软件
小众软件
WordPress大学
WordPress大学
V
Visual Studio Blog
T
The Blog of Author Tim Ferriss
U
Unit 42
酷 壳 – CoolShell
酷 壳 – CoolShell
Recent Announcements
Recent Announcements
C
Check Point Blog
IT之家
IT之家
Engineering at Meta
Engineering at Meta
N
Netflix TechBlog - Medium
A
About on SuperTechFans
aimingoo的专栏
aimingoo的专栏
D
Docker
有赞技术团队
有赞技术团队
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
阮一峰的网络日志
阮一峰的网络日志
I
InfoQ

博客园 - 雨吁的嘘

urllib在某些情况下性能低于urllib2 Unix编程艺术心得 美化fedora字体 ie6 - ie9支持Css特性的补丁 django Mysql初始化命令 Mysql post install 在线转换Postgresql 到Mysql nginx upload-progress配置 从源码安装nginx,并增加upload-porgress模块 django默认启用事务时session异常 让urllib2的DNS亦通过Proxy查询 必须为Release版本的Django网站提供404和500.html 更换Chrome为Chromium 为Redhat 6.3安装Famillcollection源 内容丰富的第三方rpm库 多余的拼音导致Python的数据类型错误 CentOS 6.3升级Python2.7.3 解决Tomcat未在IP v4监听问题 Rpm 软件库
解决urllib2的DNS远端解析问题,另Django-social-auth很好的...
雨吁的嘘 · 2012-12-19 · via 博客园 - 雨吁的嘘

Django-social-auth是一个很好的集成第三方认证的库,其支持的库种类非常多,包括常用的Facebook,twitter,google,msn,甚至还包括weibo。如果期望能够快速的集成这些账户的话,这个库是一个很好的开始。

因为众所周知的原因,在国内是没有办法访问facebook等服务的,很自然的我们希望可以通过代理的方式来让这个库工作正常。经过简单分析,这个库在底层的数据通讯方面,使用urllib2。入手点就在让urllib2支持代理了。在Python的原始库中,urllib2仅仅支持http代理,而我们使用SSH之类的用的是sock5。

经搜索发现已有网友提供了方案:

http://panweizeng.com/python-urllib2-socks-proxy.html

可是这个方法只解决了一半的问题,另一半就是DNS解析。于是又找到如下方案:

http://blog.antmanler.com/?p=471

需要说明的是,上边连接中的_create_connection与python2.7的不兼容,需要增加一个source_address=None的参数即可。

好了,至此让urllib2支持sock5的准备工作全部就绪,剩下的就是修改django-social-auth。查看其源代码,很快就能找到,这个库调用urlib2的地方被统一打包utils.py中到一个叫做dsa_open的函数。直接将上边两个链接中提到的方法,给这个函数打个补丁即可。

修改完成后的版本如下:

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
        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

    return urlopen(*args, **kwargs)

对了,这个方案需要一个叫做socksipy_branch库的支持。可以使用pip安装。

此方法仍未完全解决DNS问题,最终方案需参照:http://www.cnblogs.com/Ankh/archive/2012/12/21/2827386.html