首页 > python学习 > python中urllib模块的简单使用
2019
01-15

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.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.request as r
import urllib.parse as p
url='http://www.qingheluo.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=p.urlencode(data).encode('utf-8')
req=r.Request(url,data=d,headers=head)
req.add_header('addheader','addheader value')
with r.urlopen(req) as f:
    s=f.read()
    s=s.decode('utf-8')
    print(s)
#下面是使用代理访问的例子
proxy_support = r.ProxyHandler({'sock5': '[username:password@]localhost:1080'}) #设置请求通过的代理
opener = r.build_opener(proxy_support) #返回一个OpenerDirector实例。
r.install_opener(opener) #安装OpenerDirector实例作为默认的全局开启工具
#安装opener操作会改变后面所有操作,后面所有操作都会使用代理
#如果仅仅是一次访问使用代理用opener.open(url)访问
a =r.urlopen("http://www.qingheluo.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)
最后编辑:
作者:qingheluo
这个作者貌似有点懒,什么都没有留下。