• python---urllib模块


    仅以此纪念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()
        
    
        
        
  • 相关阅读:
    Pycharm如何自动换行
    Android逆向基础
    动态调试ELF文件Crackme
    用Hash 算法给payload瘦身
    010 editor手写pe文件
    win脱壳_压缩壳_aspack
    WannaCrypt0r分析报告
    JVM内存分区
    java设计模式(模板方法模式)
    es6
  • 原文地址:https://www.cnblogs.com/lindsay-chh/p/4721040.html
Copyright © 2020-2023  润新知