码迷,mamicode.com
首页 > 编程语言 > 详细

python---urllib模块

时间:2015-08-11 15:58:52      阅读:172      评论:0      收藏:0      [点我收藏+]

标签:

仅以此纪念python标准库学习!翻译什么会有不顺或者错误,见谅啦。。。。  后边为案例。

#coding:utf-8

import urllib


"""
本模块提供了通过万维网抓取数据的高级接口。尤其是,urlopen()函数和内置的open()相似,只是接受的参数为Urls,而不是文件名称。
有一些限制:该方法仅仅可以打开Urls进行读取,没有可用的查询操作。
"""

"------------------------------【高级接口】--------------------------------------------"
def urlopen_test(url,data,proxies,context):
    """
    .以读的方式打开url指定的网络对象。如果url没有协议标识符或者url以file://作为协议标识符,将打开一个本地文件。否则会建立一个向网络上任意服务的socket连接。如果连接无法建立,则会报错:IOError。
             如果一切顺利,则会返回一个类似文件的对象。这个对象支持下面的方法:
    read()  readline()  readlines()  fileno()  close()  info()  getcode()  geturl()
    .它也有适当的迭代器支持协议。  
    .警告:read()方法如果size参数没有指定或是负数,则直到数据流结束才会进行读取。在通常情况下,没有一个好的方法来判定来自socket的整个流已经被读取完毕。
    .除了info()  getcode()  geturl()  ,其他的方法有和file对象相同的接口。
    info()方法返回mimetools.Message类的一个实例。包括和url相关联的meta-information。当方法是HTTP时,返回的头部信息是服务器返回的html页面的头部信息(包括:Content-length 和 Content-Type).
            如果是FTP,则服务器将会返回响应该FTP请求的文件长度作为头部的Content-Length。如果是可确认的MIME类型,则将会返回Content-Type头部信息。
            如果是一个本地文件,则返回的头部信息中将会包括:文件最近一次更新时间的日期,文件长度的Content-Length,一个包含文件类型的Content-Type。
    getUrl()返回页面真实的url。在一些情况下,HTTP服务器会将一些客户请求重定向到别的URL。urlopen()方法可以透明地处理这些操作。但是一些情况下,调用者需要知道这个客户端请求被重定向到了哪个url,此时可用geturl()得到最终重定向的真实的url
    getcode()将返回发送http请求后,响应的状态码。当url不是http请求时,将返回None
    .如果url使用了http://标识,如果指定可选的参数data,则该请求被指定为POST。(通常情况下,请求是GET)。data必须是一个标准的application/x-www-form-urlencoded格式。
    
            可选的proxies参数可以被用来明确指出代理。代理必须是一个字典类型({协议:代理url}),空的字典表示没有可用的代理。当peoxies为空时(默认值),将会使用系统环境变量设置中的代理
            需要验证的代理服务器现在还不支持
    proxies代理服务器的使用如下所示:
    url="http://baidu.com:80"
    
    proxies={"http":"http://www.someproxy.com:3128"}   #代理服务器设置:以字典形式,key为协议,如:http。  value为真实url  包括端口
    f1=urllib.urlopen(url, proxies=proxies)   
    
    f2=urllib.urlopen(url,proxies={}) #将代理设置为空字典,表示不使用任何代理
    
    f3=urllib.urlopen(url,proxies=None)
   
    f4=urllib.urlopen(url)   #f3  f4  代理服务器均使用系统默认
    """
    

def urlretrieve(url,filename,reporthook,data):
    """
    .将url指定的网站对象拷贝到本地文件中。如果需要,url可以指向一个本地文件或已存在对象的有效的缓存拷贝,此时这个对象并没有被拷贝。
    .返回一个元祖:(filename,headers) filename为可找得到的本地文件名,headers是urlopen()返回对象(远程对象,可能是缓存)的info()方法的返回值。
    .异常和urlopen()方法的异常一致。
    .第二个参数:filename指出了文件拷贝目的地址(如果没有filename,地址将会是自动生成的临时文件地址)。
    .第三个参数是一个方法,一旦网络连接建立且每一个块被读取后,这个hook方法就会被调用。hook函数需要三个参数:到目前已经被读取的块数量,每块的字节数,文件大小。在旧有的FTP服务器上,对于retrieve请求,在响应中,并不返回文件大小,此时文件大小可能为-1
    .如果url使用"http://"标识符,data参数如果被指定,则该请求为POST(默认是GET请求)。data格式必须是标准的:application/x-www-form-urlencoded格式。
    .在2.5版本后,如果发现可用的数据大小小于 预期大小(在Content-Length头信息中的大小),会报错:ContentTooShortError。如:当下载被中断时。
    .Content_length是文件大小的下限。如果有更多信息需要读取,则urlretrieve会读取更多的信息。 但是如果实际可读信息小于预期Content-Length,则会报错
    .在这个情况下,你仍然可以检索被下载的数据,它被存储在异常实例的content属性中。
    .当没有提供Content-Length头信息,urlretrieve不会检查已经下载了多少数据,仅仅是返回对象。这个时候不能确保下载成功。
    """  
    
    
"""
urllib.__urlopener
公共方法urlopen()和urlretrieve()会创建一个FancyURLopener类的实例。并用这个实例来操作urlopen()和urlretrieve()的请求。
为了覆盖这个功能,可以创建一个URLopener或者FancyURLopener的子类,然后再调用urlopen()和urlretrieve()方法之前将子类实例赋值给urllib._urlopener属性。
如:用户想要定义一个用户自定义的头信息。代码如下;
class AppURLopener(urllib.FancyURLopener):
    version="App/1.7"

urllib._urlopener=AppURLopener()
"""

def urlcleanup():
    """
    .清除之前的urlretrieve()方法可能带来的缓存。
    """

"------------------------------【公共功能】--------------------------------------------"
def quote_test(string,safe):
    """
            使用%xx逃逸字符来代替string中的特殊字符。 字母、数字、下划线将不会被quoted。默认情况下这个方法被用来quote url中的路径分隔符。 
    safe参数用来标识不会被quote的字符串,默认是"/"
    """
    print urllib.quote("http://localhost:8080/#s~d") #结果http%3A//localhost%3A8080/%23s%7Ed  将字母、数字、下划线和默认的safe/之外的特殊字符转化为%xx格式的字符串
    print urllib.quote("http://localhost:8080/#s~d",safe=":") #结果http:%2F%2Flocalhost:8080%2F%23s%7Ed  此时除了:和字母、数字、下划线之外的所有特殊字符均被转化为%xx类型的字符串
    print urllib.quote("http://localhost:8080/#s~d",safe=":/~") #结果为:http://localhost:8080/%23s~d  safe中的字符均没有被quote
    
    
def quote_plus(string,safe):
    """
            类似于quote()。这个方法 会将空格转化为+。被用来quote html。字符串中的"+",会被quote。直到"+"被包含在safe中
    """   
    print urllib.quote_plus("<html><body>      welcome!~n  </body></html>")  #结果:%3Chtml%3E%3Cbody%3E++++++welcome%21%7En++%3C%2Fbody%3E%3C%2Fhtml%3E
    print urllib.quote_plus("<body>   welcome++Lindsay  </body>") #%3Cbody%3E+++welcome%2B%2BLindsay++%3C%2Fbody%3E   此时+也被quote
    print urllib.quote_plus("<body>   welcome++Lindsay  </body>","+") #%3Cbody%3E+++welcome++Lindsay++%3C%2Fbody%3E  此时"+"正常显示
    
def unquote(string):
    "quote反操作"
    q1=urllib.quote("http://localhost:8080/~@#")
    print q1
    src=urllib.unquote(q1)
    print src
    
def unquote_plus(string):
    "quote_plus反操作"
    q1=urllib.quote_plus("<html><head></head><body>        WELCOME++Lindsay        </body></html>")
    print q1
    src=urllib.unquote_plus(q1)
    print src
    
def urlencode(query,doseq):
    """
    .将一个映射对象或二元元组的序列转化为完全编码的字符串。将对象转化为urlopen()中可用的data参数。将字典或 表单数据转化为POST请求的参数是有用的。返回值是类似于:f1=v1&f2=v2&f3=v3格式的字符串。(f和v均是由quoteplus转化而来)
            当二元元组集被用来作为查询条件,每个元组的第一个参数都是key,第二个元素是value。
    """
    d={"a":"lindsay","b":12,"c":"56788","d":"234"}
    print d
    print urllib.urlencode(d) #a=lindsay&c=56788&b=12&d=234

def pathname2url(path):
    """
            将路径名称path从本地语法转化为URL中路径组件使用的形式。 返回值已经被用quote()函数处理过。 并不会生成一个完整的URL
    """
    print urllib.pathname2url("C://TEST.TXT")  #///C:///TEST.TXT
    
def url2pathname(path):
    """
            将路径组件path从完全编码的url转化为本地语法形式。path并不是一个完整的URL。这个方法使用unquote()来堆path解码
    """
    uf1=urllib.pathname2url("C://test.txt")
    print uf1
    path=urllib.url2pathname(uf1)
    print path
    
def getproxies():
    """
    .返回协议和代理服务器URL的映射字典。
    """
    d=urllib.getproxies()
    print d
    print type(d)
    
    
"------------------------------【URL Opener objects】--------------------------------------------"
"""
urllib.URLopener([proxies[,context[,**509]]])
打开和阅读URLs的基本类。除非你要支持打开的对象使用http:  ftp:  file:  之外的协议,否则应该使用:FancyURLopener。
默认情况下,发送一个用户自定义的urllib头部信息/VVV ,VVV是urllib的版本号。应用可以通过继承URLopener或FancyURLopener,并在子类定义时为version赋值来自定义自己的User_Agent头部信息,
可选的proxies参数应该是协议和代理服务器URL映射的字典,如果proxies为{},则不适用任何代理。默认proxies为None,此时会使用系统配置的代理。
**509可以被用来当客户端使用http:协议时进行客户端验证.
如果服务端返回错误码时,URLopener对象将会报错:IOError

open(fillurl[,data]):
    使用合适的协议打开fillurl。这个方法会建立缓存和代理信息,然后使用输入参数调用适当的open方法。如果没有找到合适的协议,则会调用open_unknown()。data参数和urlopen()中一致
open_unknown()
   重写接口,打开未知的url类型
retrieve(url[,filename[mreporthook[,data]]])
version


urllib.FancyURLopener(...)
   提供了对于http响应码:301  302  303  307 401的默认处理。对于上述列出的30X响应码,本地header被用来查询真正的url。对于401响应码(需要认证),会执行基本的认证。
   对于30X响应码,递归次数通过maxtries属性来限制。默认是10
   对于其他响应码,将会调用:http_error_default()方法。你可以在子类中重写这个方法来适当地处理这个错误。
   根据RFC 2616,POST请求的301和302响应如果没有用户确认是不会自动进行重定向的。事实上,浏览器会将POST改变成GET,然后自动进行重定向。urllib复制了这个操作
   
异常:urllib.ContentTooShortError(msg[,content])   



urllib的限制:
目前仅仅支持以下的协议:http  ftp  localfiles
"""

"----------------------------------------------【examples】-----------------------------------"
def get_test():
    params = urllib.urlencode({spam: 1, eggs: 2, bacon: 0})
    f = urllib.urlopen("http://www.musi-cal.com/cgi-bin/query?%s" % params)
    print f,type(f)
   # print f.read()
    print f.info()
    print f.geturl()
    print f.getcode()
    ‘‘‘
            结果:
    <addinfourl at 26900880 whose fp = <socket._fileobject object at 0x019B0730>> <type ‘instance‘>
    Cache-Control: private
    Content-Type: text/html; charset=utf-8
    Server: Microsoft-IIS/7.5
    X-AspNet-Version: 4.0.30319
    X-Server-Identity: 1
    X-Powered-By: ASP.NET
    Date: Tue, 11 Aug 2015 06:30:41 GMT
    Connection: close
    Content-Length: 138689

    http://www.concertvault.com/?eggs=2&bacon=0&spam=1
    200
    ‘‘‘
  
def post_test():
    params = urllib.urlencode({spam: 1, eggs: 2, bacon: 0})
    f = urllib.urlopen("http://www.musi-cal.com/cgi-bin/query",params)
    print f,type(f)
   # print f.read()
    print f.info()
    print f.geturl()
    print f.getcode()  #所得结果和get_test()一致
    
def proxies_test():
    "使用了指定的http代理,覆盖了系统设置"
    ‘‘‘
    proxies = {‘http‘: ‘http://proxy.example.com:8080/‘}
    opener = urllib.FancyURLopener(proxies)
    f = opener.open("http://www.python.org")
    ‘‘‘
    "用上述代理服务器访问不到"
    f=urllib.urlopen("http://www.python.org")
    print f.info()
    print f.geturl()
    print f.getcode()
    
    print "--------------------------------------------------"
    "使用空的代理"
    proxies={}
    opener=urllib.FancyURLopener(proxies)
    f=opener.open("http://www.python.org")
    print f.info()
    print f.geturl()
    print f.getcode()
    
    
def get_remote_info():
    "利用urllib获取远程资源"
    fp=urllib.urlopen("http://www.python.org")
    op=open("out.html","wb")
    n=0
    
    while 1:
        s=fp.read(8192)
        if not s:
            break
        op.write(s)
        n=n+len(s)
    fp.close()
    op.close()
    
    for k,v in fp.headers.items():
        print k,"=",v
    
    print "copied",n ,"bytes from ",fp.url


"""
urlopen 函数实际上是一个辅助函数,会创建一个FancyURLopener类的实例并调用它的open方法。 也可以继承这个类完成特殊的行为。
例如下例会在必要时自动登录服务器
"""
class myURLOpener(urllib.FancyURLopener):
    "read an URL,with automatic HTTP authentication"
    
    def setpasswd(self,user,passwd):
        self.__user=user
        self.__passwd=passwd
        
    def prompt_user_passwd(self,host,realm):
        return self.__user,self.__passwd
   
def auto_authentication():
    urlopener=myURLOpener()
    urlopener.setpasswd("mulder", "trustnol")
    
    fp=urlopener.open("http://www.secretlabs.com")
    print fp
    print fp.geturl()
    print fp.getcode()
    print len(fp.readlines())
        
    
    
if __name__ == "__main__":
    """
    urlopen_test(None, None, None, None)
    quote_test(None,None)
    quote_plus(None,None)
    unquote(None)
    unquote_plus(None)
    urlencode(None,None)
    pathname2url(None)
    url2pathname(None)
    getproxies()
    get_test()
    post_test()
    proxies_test()
    get_remote_info()
    """
    
    auto_authentication()
    

    
    

python---urllib模块

标签:

原文地址:http://www.cnblogs.com/lindsay-chh/p/4721040.html

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