python中urllib模块的简单使用
python为了统一,python把urllib、urllib2两个模块这两个模块的功能做了整合,整合成了包含四个功能模块的urllib的模块包:
urllib.request:用于打开和读取网络资源(url)
urllib.error:包含和处理由urllib.request模块引发的异常
urllib.parse:用于解析网络资源(url)
urllib.robotparser:用于解析robots.txt文件
urllib.request:
urllib.request.urlopen(url/Request,data=None,[timeout,]*,cafil=None,capath=None,cadefault=False):打开一个url地址或Request对象url/Request:打开的可以是一个url地址,也可以是一个Request对象
data:是指定要发送到服务器的数据,如不需要默认为None,目前,HTTP请求是唯一使用数据的请求。如果未提供Content-Length或Transfer-Encoding标头字段,将根据数据类型设置这些标头。urllib.parse.urlencode()函数采用2元组的映射或序列,并以此格式返回ASCII字符串,在用作数据参数之前,应将其返回的ASCII字符编码为字节。如果data参数存在,则应包含适当的Content-Type标头。如果未提供此标头且数据不是None,则默认情况下将添加Content-Type:application / x-www-form-urlencoded,即使用HTTP的POST请求方法。
timeout参数指定操作的超时(以秒为单位,如未指定,使用全局默认超时设置),仅适用于HTTP,HTTPS和FTP连接。
cafile和capath参数为HTTPS请求指定一组可信CA证书。cafile指向包含一组CA证书的单个文件,capath指向散列证书文件的目录。可在ssl.SSLContext.load_verify_locations()中找到更多信息。从版本3.6开始不推荐使用cafile,capath和cadefault以支持上下文。请改用ssl.SSLContext.load_cert_chain(),或者让ssl.create_default_context()为您选择系统的可信CA证书。
返回一个HTTPResponse对象,该对象可用作上下文管理器并具有下面常用的方法和属性:
geturl()返回检索到的资源的URL,通常用于确定是否遵循重定向
info()返回页面的元信息(响应头信息)
getcode()返回响应的HTTP状态代码
read([n])返回当前指针之后的n个字节,省略n参数返回所有内容。
getheader(name,defalut=None)返回响应头中name的值,如果没有name,则返回default值。
getheaders()返回响应头(header_name,header_value)元组组成的列表。
fileno()返回文件描述符。
version:服务器使用的HTTP协议版本。10表示HTTP / 1.0,11表示HTTP / 1.1。
status:服务器返回的状态代码。
reason:服务器返回的原因短语。
closed:如果流被已经关闭返回True。
urllib.parse:用于编码发送的数据或解析url地址
url编码及解码urllib.parse.urlencode(data) #将一个dict数据转化为key1=val1&key2=val2...的字符串并进行url编码 urllib.parse.parse_qs(str) #解码urlencode编码为dict格式 urllib.parse.quote(str) #符串进行url编码 urllib.parse.unquote(str) #符串url编码的字符串解码url解析
url解析提供了两个方法 urllib.parse.urlsplit(url, scheme='', allow_fragments=True) urllib.parse.urlparse(url, scheme='', allow_fragments=True) 两个方法的唯一区别就是urlparse方法返回中多一个params项(很少用到) scheme参数指定url的协议,如果url中包含协议则忽略此参数 allow_fragments参数指定是否解析锚文本,如果为False则锚文本包含在query字段中,fragment为空 返回一个SplitResult对象,对象中包含固定的字段,使用.字段来获取指定字段 demo = urllib.parse.urlparse('https://www.domain.com/python/?demo=true#test') print(demo) ParseResult(scheme='https', netloc='www.domain.com', path='/python/', params='', query='demo=true', fragment='test') print(demo.path) /python/
urllib.request.Request:
urllib.request.Request(url,data=None,headers={},origin_req_host=None,unverifiable=False,method=None):此类是URL请求的抽象。url应该是包含有效URL的字符串。
data参数和urllib.request.urlopen()中的data用法相同
headers应该是一个字典(字典中出现中文会报错),并且将被视为使用每个键和值作为参数调用add_header(key,value)方法
method应该是一个字符串,表示将使用的HTTP请求方法(例如'HEAD')。如果提供,则其值 存储在method属性中,并由get_method()使用。如果数据为None,则默认为'GET',否则为'POST'。子类可以通过在类本身中设置method属性来指示不同的默认方法。
返回一个Request对象,该对象可用urllib.request.urlopen()打开并具有下面常用的方法和属性:
Request.full_url:获取请求URL,具有setter,getter和deleter的属性
Request.type:返回协议名
Request.headers:返回发送到服务器的请求头的dict
Request.host:返回主机名和端口号(80端口默认省略)
Request.origin_req_host:请求的原始主机,没有端口。
Request.selector:URI路径(域名后面的所有字符串)。
Request.data:请求传递的数据,如果未传递,则为None。
Request.header_items():返回请求头的元组(header_name,header_value)组成的列表。
Request.method:返回HTTP请求方法。默认情况下,其值为None。
Request.get_method():返回HTTP请求方法。如果Request.method不是None,则返回其值,如果Request.data为None则返回'GET',如果不是则返回'POST',这仅对HTTP请求有意义。
Request.add_header(key, val):在发送到服务器的标头列表中添加一个标头。
urllib.request.urlretrieve()
urllib.request.urlretrieve(url[, filename[, reporthook[, data]]])将由URL表示的网络对象复制到本地文件filename:指定保存到本地的路径和文件名(如果未指定该参数,urllib会生成一个临时文件来保存数据)
reporthook:回调函数,建立网络连接时调用一次,然后在每个块读取之后调用一次,将传递三个参数:已传输的块数、每块代表的字节大小和文件的总字节大小,第三个参数可能是-1,因为在旧的FTP服务器上不返回响应检索请求的文件总大小。我们可以利用这个回调函数来显示当前的下载进度。
data:指post到服务器的数据。
该方法返回一个包含两个元素的元组(filename, headers),filename表示保存到本地的路径和文件名,header表示服务器的响应头。
def callbackfunc(blocknum, blocksize, totalsize): '''回调函数 @blocknum: 已经下载的数据块 @blocksize: 数据块的大小 @totalsize: 远程文件的总大小 ''' percent = 100.0 * blocknum * blocksize / totalsize if percent > 100: percent = 100 print ("%.2f%%"% percent) urllib.request.urlretrieve('http://a.com/down.zip','new.zip',callbackfunc)
使用实例
import urllib.requestimport urllib.parse
url='http://www.domain.com/test/test.php/aaa/aaa.html?hand=kias';
head={'name-diy':'myname','test':'diy','user-agent':'diy agent'}
data=[('key','value'),('username',"yonghuming"),('password','mima')]
data={'key':'value','username':"yonghuming",'password':'mima'}以上两种data数据格式都可以
d=urllib.parse.urlencode(data).encode('utf-8')
req=urllib.request.Request(url,data=d,headers=head)
req.add_header('addheader','addheader value')
with urllib.request.urlopen(req) as f:s=f.read() s=s.decode('utf-8') print(s)
下面是使用代理访问的例子
proxy_support = urllib.request.ProxyHandler({'sock5': '[username:password@]localhost:1080'}) #设置请求通过的代理
opener = urllib.request.build_opener(proxy_support) #返回一个OpenerDirector实例。
urllib.request.install_opener(opener) #安装OpenerDirector实例作为默认的全局开启工具安装opener操作会改变后面所有操作,后面所有操作都会使用代理
如果仅仅是一次访问使用代理用opener.open(url)访问
a =urllib.request.urlopen("http://www.domain.com/test/test.php").read().decode("utf8")
print(a)
异常处理
urllib.error.URLError:这个异常可能产生的原因:网络无连接、连接不到指定服务器、服务器不存在。异常中包含一个reason属性,里面有这次异常的int类型的错误代号和str类型的错误原因描述urllib.error.HTTPError:是urllib.error.URLError的一个子类,用urllib.request.urlopen()方法发出一个请求时,服务器上都会对应一个应答对象response,其中包含一个数字”状态码”。因为urllib模块可以自动处理重定向,也就是3开头的状态码可以被处理,并且100-299范围的号码指示成功,所以urllib.error.HTTPError异常状态码我们平时只能看到400-599。
urllib.error.HTTPError有一个code属性,就是状态码,另外还有reason属性,这是从父类URLError继承的属性。
import urllib.error import urllib.request req = urllib.request.Request('http://a.com') try: urllib.request.urlopen(req) except urllib.error.HTTPError as e: print (e.code,e.reason) except urllib.error.URLError as e: print (e.reason)父类的异常应当写到子类异常的后面,如果子类捕获不到,那么可以捕获父类的异常,上例中如果捕获到了HTTPError,则输出code,不会再处理URLError异常。如果发生的不是HTTPError,则会去捕获URLError异常,输出错误原因。还可以加入hasattr对属性进行判断,代码改写如下:
try: urllib.request.urlopen(req) except urllib.error.URLError as e: if hasattr(e,"code"): print (e.code) if hasattr(e,"reason"): print (e.reason)