urllib源码阅读
urllib底层是对httplib的封装,使之更易用
一般用法:
import urllib
res = urllib.urlopen('http://www.baidu.com')
resp.read()
贴下urlopen的代码
def urlopen(url, data=None, proxies=None, context=None):
......
global _urlopener
if proxies is not None or context is not None:
opener = FancyURLopener(proxies=proxies, context=context)
elif not _urlopener:
opener = FancyURLopener()
_urlopener = opener
else:
opener = _urlopener
if data is None:
return opener.open(url)
else:
return opener.open(url, data)
可以看出urlopen接收四个参数,url(地址)、data(参数)、proxies(代理,非必填)、context(代理用,非必填)。从代码中可以看出,urlopen实际上都是在调用FancyURLopener的实例,返回该实例中open方法。而FancyURLopener又是URLopener的子类。
URLopener包含的一些属性和方法
__tempfiles 是一个list,用来存储从网络爬取到本地的本地文件
addheader 添加http头
open 用来分发处理各式请求,调用splittype函数对请求地址进行处理,得到url的格式,再调用相应的实例方法
if not hasattr(self, name): # name是由'open_' 拼上协议名
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]
形如上述代码,比如http请求,首先拼出open_http名称,然后通过getattr(self, name)(url)进行调用。
open函数在此处好比一个中转站,对各式请求处理判断后,找到目标函数,进行更准确的操作。
open_http、open_https、open_file、open_local_file、open_ftp、open_data 执行更为精细的请求操作,接收的参数包括url(必填)、data(非必填)
http_error http请求错误,如果open在处理http请求过程中出现错误,将调用该方法
http_error_default http 请求默认错误
FancyURLopener 细分了http请求的返回状态
请求返回数据基本上是在操作addbase或者addbase的子类,它实现了一些操作文件的方法,比如read、readlines等等
源码中有很多的小函数,用来处理url或者参数,注释中写明了这些小函数的作用,如下:
# Utilities to parse URLs (most of these return None for missing parts):
# unwrap('<URL:type://host/path>') --> 'type://host/path'
# splittype('type:opaquestring') --> 'type', 'opaquestring'
# splithost('//host[:port]/path') --> 'host[:port]', '/path'
# splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'
# splitpasswd('user:passwd') -> 'user', 'passwd'
# splitport('host:port') --> 'host', 'port'
# splitquery('/path?query') --> '/path', 'query'
# splittag('/path#tag') --> '/path', 'tag'
# splitattr('/path;attr1=value1;attr2=value2;...') ->
# '/path', ['attr1=value1', 'attr2=value2', ...]
# splitvalue('attr=value') --> 'attr', 'value'
# unquote('abc%20def') -> 'abc def'
# quote('abc def') -> 'abc%20def')

浙公网安备 33010602011771号