码迷,mamicode.com
首页 > Web开发 > 详细

urllib源码简单分析

时间:2015-09-20 01:45:30      阅读:349      评论:0      收藏:0      [点我收藏+]

标签:

对下面这段代码做分析

import urllib
params = urllib.urlencode({wd: python})
f = urllib.urlopen("http://www.baidu.com/s?%s" % params)
print f.read()

这是一段简单读取url内容的代码

此处最关键的是urlopen,通过查看,可以看到urlopen的代码如下

def urlopen(url, data=None, proxies=None):
    """Create a file-like object for the specified URL to read from."""
    from warnings import warnpy3k
    warnpy3k("urllib.urlopen() has been removed in Python 3.0 in "
             "favor of urllib2.urlopen()", stacklevel=2)

    global _urlopener
    if proxies is not None:
        opener = FancyURLopener(proxies=proxies)
    elif not _urlopener:
        opener = FancyURLopener()
        _urlopener = opener
    else:
        opener = _urlopener
    if data is None:
        return opener.open(url)
    else:
        return opener.open(url, data)

通过一个FancyURLopener的opener实例,因为这里没有proxies参数,所以调用到opener = FancyURLopener()这一句。

技术分享

然后返回opener.open(url),绑定到f实例上。在这里,有两个关键,一个是opener实例,一个是open方法。

  • opener:先来说说opener,opener是FancyURLopener()的对象,而FancyURLopener的父类是URLopener基类,而FancyURLopener这个类本身只做了一些http的异常响应处理,因此我们需要了解核心的基类,也就是看看URLopener到底做了什么?
  1. URLopener:通过查看源码,发现URLopener的主要处理方法是open。
    def open(self, fullurl, data=None):
        """Use URLopener().open(file) instead of open(file, ‘r‘)."""
        fullurl = unwrap(toBytes(fullurl))
        # percent encode url, fixing lame server errors for e.g, like space
        # within url paths.
        fullurl = quote(fullurl, safe="%/:=&?~#+!$,;‘@()*[]|")
        if self.tempcache and fullurl in self.tempcache:
            filename, headers = self.tempcache[fullurl]
            fp = open(filename, rb)
            return addinfourl(fp, headers, fullurl)
        urltype, url = splittype(fullurl)
        if not urltype:
            urltype = file
        if urltype in self.proxies:
            proxy = self.proxies[urltype]
            urltype, proxyhost = splittype(proxy)
            host, selector = splithost(proxyhost)
            url = (host, fullurl) # Signal special case to open_*()
        else:
            proxy = None
        name = open_ + urltype
        self.type = urltype
        name = name.replace(-, _)
        if not hasattr(self, name):
            if proxy:
                return self.open_unknown_proxy(proxy, fullurl, data)
            else:
                return self.open_unknown(fullurl, data)
        try:
            if data is None:
                return getattr(self, name)(url)
            else:
                return getattr(self, name)(url, data)
        except socket.error, msg:
            raise IOError, (socket error, msg), sys.exc_info()[2]

open通过处理url,将name拼接成name = ‘open_‘ + urltype的格式,也就是说,如果是http请求,则name为open_http。在上文那段代码里,最后调用返回的是getattr(self, name)(url),而由于name变成了open_http,则继续调用open_http方法。在这里可以看出,urllib根据你的type来给出不同的方法作处理。

那么又要看看open_http干了什么

 

urllib源码简单分析

标签:

原文地址:http://www.cnblogs.com/alexkn/p/4822707.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!