zoukankan      html  css  js  c++  java
  • python3之模板pycurl探测web服务质量

    1、pycurl简介

    pycURL是libcurl多协议文件传输库的python接口,与urllib模块类似,PycURL可用于从python程序中获取由URL标识的对象,功能很强大,libcurl速度非常快pycurl作为libcurl之上的薄包装,速度也非常快;支持多种协议SSL,身份验证和代理选项;用于网络操作的套接字允许将pycurl集成到应用程序的I/O循环中。

    libcurl是一个免费且易于使用的客户端URL传输库,支持DICT,FILE,FTP,FTPS,Gopher,HTTP,HTTPS,IMAP,IMAPS,LDAP,LDAPS,POP3,POP3S,RTMP,RTSP,SCP, SFTP,SMTP,SMTPS,Telnet和TFTP。libcurl支持SSL证书,HTTP POST,HTTP PUT,FTP上传,基于HTTP表单的上传,代理,cookies,用户名密码认证(Basic,Digest,NTLM,Negotiate,Kerberos4),文件传输恢复,http代理隧道等等。
    libcurl具有很高的可移植性,它可以在多种平台上构建和运行,包括Solaris,NetBSD,FreeBSD,OpenBSD,Darwin,HPUX,IRIX,AIX,Tru64,Linux,UnixWare,HURD,Windows,Amiga,OS / 2,BeOs,Mac OS X,Ultrix,QNX,OpenVMS,RISC OS,Novell NetWare,DOS等等...

    libcurl是免费的,线程安全的,兼容IPv6,功能丰富, 支持良好,速度快,记录完整,已被许多已知的大型成功公司和众多应用程序使用。

    pycurl安装:

    pycurl安装要求:需要python版本在2.7或者3.4到更高版本;需要libcurl版本在7.19.0或更高版本。

    在Unix上使用操作系统的包管理工具来安装pycurl更容易,它将根据需要安装libcurl和其他依赖项.

    esay_install pycurl
    pip install pycurl

    源码安装:

    #要求 curl-config 包支持,需要源码方式重新安装 curl
    wget http://curl.haxx.se/download/curl-7.36.0.tar.gz
    tar -zxvf curl-7.36.0.tar.gz
    cd curl-7.36.0
    ./configure
    make && make install
    export LD_LIBRARY_PATH=/usr/local/lib
    
    wget https://pypi.python.org/packages/source/p/pycurl/pycurl-7.43.0.2.tar.gz
    --no-check-certificate
    tar -zxvf pycurl-7.19.3.1.tar.gz
    cd pycurl-7.19.3.1
    python setup.py install --curl-config=/usr/local/bin/curl-config
    #校验安装结果如下:
    >>> import pycurl
    >>> pycurl.version
    'PycURL/7.43.0.2 libcurl/7.36.0 OpenSSL/1.0.1e zlib/1.2.3'

    2、pycurl模块功能

    pycurl.globalz_init(option):初始化curl环境

    选项可以是常量之一:pycurl.GLOBAL_SSL  pycurl.GLOBAL_WIN32  pycurl.GLOBAL_ALL  pycurl.GLOBAL_NOTHING  pycurl.GLOBAL_DEFAULT 

    对应于libcurl中的curl_global_init

    pycurl.global_cleanup():清理curl环境,对应于libcurl中的curl_global_cleanup

    pycurl.version:显示pycurl版本信息以及libcurl,openSSL,zlib依赖项的版本信息,对应libcurl中的curl_version

    pycurl.version_info():用元祖返回版本信息,对应libcurl中的curl_version_info

    class pycurl.Curl:创建一个新的curl对象,它对应libcurl中的句柄.

    class pycurl.CurlMulti:创建一个与libcurl中的句柄相对应的新curlMulti对象curlM

    class pycurl.CurlShare:创建一个与libcurl中的句柄相对应的新CurlShare对象curlSH

    3、curl对象

    class pycurl.Curl:创建一个新的curl对象

    curl对象具有以下方法:

    close():关闭句柄并结束curl会话

    setopt(option,vlaue):设置curl会话选项,对应于libcurl中的curl_easy_setopt

    option指定要设置的选项,pycurl定义了与curlopt_*libcurl中的常量相对应的常量,但CURLOPT_前缀被删除

    • (pycurl.CONNECTTIMEOUT, 5) #连接的等待时间,设置为0则不等待
    • (pycurl.TIMEOUT, 5) #请求超时时间
    • (pycurl.NOPROGRESS, 0) #是否屏蔽下载进度条,非0则屏蔽
    • (pycurl.MAXREDIRS, 5) #指定HTTP重定向的最大数
    • (pycurl.FORBID_REUSE, 1) #完成交互后强制断开连接,不重用
    • (pycurl.FRESH_CONNECT,1) #强制获取新的连接,即替代缓存中的连接
    • (pycurl.DNS_CACHE_TIMEOUT,60) #设置保存DNS信息的时间,默认为120秒
    • (pycurl.URL,"http://www.baidu.com") #指定请求的URL
    • (pycurl.USERAGENT,"Mozilla/5.2 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50324)") #配置请求HTTP头的User-Agent
    • (pycurl.HEADERFUNCTION, getheader) #将返回的HTTP HEADER定向到回调函数getheader
    • (pycurl.WRITEFUNCTION, getbody) #将返回的内容定向到回调函数getbody
    • (pycurl.WRITEHEADER, fileobj) #将返回的HTTP HEADER定向到fileobj文件对象
    • (pycurl.WRITEDATA, fileobj) #将返回的HTML内容定向到fileobj文件对象

    更多选项...

    perform():执行文件传输,对应于libcurl中的curl_easy_perform,失败时会引发pycurl.error异常

    perform_rb():执行文件传输并将响应主体返回为字节字符串,此方法将响应正文保存在StringIO(python 2)或BytelsIO(python 3)实例中,然后调用执行文件传输,返回str或者bytes实例,传输错误将引发pycurl.error异常。

    perform_rs():以字符串形式执行文件传输并返回响应正文,

    在Python 2中,此方法将响应正文保存在一个StringIO实例中,然后调用执行 文件传输,然后返回StringIO实例的值。此行为与perform_rb相同。
    在Python 3中,此方法将响应正文保存在BytesIO实例中,然后调用执行 文件传输,然后使用Python的默认编码解码响应正文,并将解码的正文作为Unicode字符串(str实例)返回

    getinfo(option):

    从curl会话中提取并返回信息,在调用时使用Python的默认编码解码字符串数据。对应于libcurl中的curl_easy_getinfo。getinfo除非perform被调用并完成,否则不应调用该方法 。

    option选项是一个常数,对应CURLINFO_*于libcurl中的一个 常量。大多数选项不变名称与相应的CURLINFO_*与恒定的名字CURLINFO_去掉前缀,例如CURLINFO_CONTENT_TYPE是访问 pycurl.CONTENT_TYPE

    • (pycurl.HTTP_CODE) #返回的HTTP状态码
    • (pycurl.TOTAL_TIME) #传输结束所消耗的总时间
    • (pycurl.NAMELOOKUP_TIME) #DNS解析所消耗的时间
    • (pycurl.CONNECT_TIME) #建立连接所消耗的时间
    • (pycurl.PRETRANSFER_TIME) #从建立连接到准备传输所消耗的时间
    • (pycurl.STARTTRANSFER_TIME) #从建立连接到传输开始消耗的时间
    • (pycurl.REDIRECT_TIME) #重定向所消耗的时间
    • (pycurl.SIZE_UPLOAD) #上传数据包大小
    • (pycurl.SIZE_DOWNLOAD) #下载数据包大小
    • (pycurl.SPEED_DOWNLOAD) #平均下载速度
    • (pycurl.SPEED_UPLOAD) #平均上传速度
    • (pycurl.HEADER_SIZE) #HTTP头部大小

    更多内容...

    getinfo_raw(option):

    从curl会话中提取并返回信息,将字符串数据作为字节字符串返回。对应于libcurl中的curl_easy_getinfo。getinfo_raw除非perform被调用并完成,否则不应调用该方法 

    reset():将在curl句柄上设置的所有选项重置为默认值,但保留活动连接,会话ID缓存,DNS缓存,Cookie和共享。

    unsetopt(option):将卷曲会话选项重置为其默认值

    4、CurlMulti对象

     Class pycurl.CurlMulti  :创建一个与libcurl中的句柄相对应的新CurlMulti对象curlM

    CurlMulti对象的方法:

    close():关闭对象应用

    add_handle(curl object):将一个现有和有效的curl对象添加到curlMulti对象中

    remove_handle(curl object):从curlMulti对象中移除现有的有效curl对象

    perform():状态元组和活动curl对象的数量

    setopt(option,value):设置curl多选项,option选项指定要设置的选项,pycurl定义了与curlmopt_*libcurl中的常量相对应的常量,但curlmopt_前缀被替换为m_前缀,例如,CURLMOPT_PIPELINING在PycURL中公开为pycurl.M_PIPELINING

    fdset():具有活动文件描述符的列表元祖,可读写

    timeout():返回等待操作的时间

    5、使用实例

    要使用PycURL发布网络请求,需要以下步骤:

    (1)创建一个pycurl.Curl市里

    (2)使用setopt设置选项

    (3)通过perform来执行操作

    (4)赛选获得资源

    例1:简单获得网络资源

    #!/usr/bin/env python
    #coding:utf8
    import pycurl
    from io import BytesIO
    
    buffer = BytesIO()  #创建缓存对象
    c = pycurl.Curl()  #创建curl实例
    c.setopt(c.URL,'http://www.cnblogs.com/zhangxinqi/')  #设置资源路径
    c.setopt(c.WRITEDATA,buffer)  #设置资源数据写入到缓存对象
    c.perform()  #执行
    c.close()
    
    body=buffer.getvalue().decode()  #读取缓存中的资源并解码
    print(body)

    例2:获取https网络资源

    #!/usr/bin/env python
    #coding:utf8
    
    import pycurl
    import certifi  #导入根证书集合,用于验证SSL证书可信和TLS主机身份
    from io import BytesIO
    
    buffer = BytesIO()
    c = pycurl.Curl()
    c.setopt(c.URL,'https://www.w3cschool.cn/python/')
    c.setopt(c.WRITEDATA,buffer)
    c.setopt(c.CAINFO,certifi.where()) #设置指定证书验证包
    c.perform()
    c.close()
    
    body=buffer.getvalue()
    print(body.decode('utf-8'))

    例3:获取网站编码自动解码

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @Time    : 2018/6/6 9:21
    # @Author  : Py.qi
    # @File    : pycurl_auto.py
    # @Software: PyCharm
    import certifi
    import pycurl
    import re
    try:
        from io import BytesIO
    except ImportError:
        from io import StringIO as BytesIO
    
    headers = {}
    def header_function(header_line):
        #python3上需要解码
        header_line = header_line.decode('iso-8859-1')
        if ':' not in header_line:
            return
        name, value = header_line.split(':', 1)
        name = name.strip()
        value = value.strip()
        name = name.lower()
        headers[name] = value
    url1 = 'http://www.mytju.com/classcode/tools/encode_gb2312.asp'
    url2 = 'http://psutil.readthedocs.io/en/latest/'
    url3 = 'https://www.cnblogs.com/ddxueyu/archive/2015/07/11/4638414.html'
    buffer = BytesIO()
    c = pycurl.Curl()
    c.setopt(c.URL,url2)
    c.setopt(c.CAINFO,certifi.where())
    c.setopt(c.WRITEFUNCTION, buffer.write)
    c.setopt(c.HEADERFUNCTION, header_function) #头文件返回给函数
    c.perform()
    c.close()
    body = buffer.getvalue()
    encoding = None
    print(headers)
    if 'content-type' in headers:
        content_type = headers['content-type'].lower()
        print(content_type)
        match = re.search('charset=(S+)', content_type)
        print(match)
        if match:
            encoding = match.group(1)
            print('Decoding using %s' % encoding)
        else:
            patt = re.search(r'charset="(S+)"',str(body))
            encoding=patt.group(1).lower()
            print('Decoding using %s' % encoding)
    else:
        encoding = 'iso-8859-1'
    print(encoding)
    print(body.decode(encoding))

    例4:响应信息写入文件

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @Time    : 2018/6/6 10:20
    # @Author  : Py.qi
    # @File    : pycurl_writeFiel.py
    # @Software: PyCharm
    
    import pycurl
    
    with open('out.html','wb') as f:
        c = pycurl.Curl()
        c.setopt(pycurl.URL,'http://www.quanjing.com/')
        c.setopt(pycurl.WRITEDATA,f)  #配置响应内容写入到文件
        c.perform()
        c.close()

    例5:使用 pycurl 的 setopt 与 getinfo 方法实现 HTTP 服务质量的探测

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @Time    : 2018/6/6 10:38
    # @Author  : Py.qi
    # @File    : check_pycurl.py
    # @Software: PyCharm
    import pycurl
    from io import BytesIO
    
    class ex_response(object):
        def __init__(self,url):
            self.buffer = BytesIO()
            self.c = pycurl.Curl()
            self.c.setopt(pycurl.URL,url)
            self.c.setopt(pycurl.WRITEDATA, self.buffer)
            self.c.setopt(pycurl.WRITEHEADER,self.buffer)
            try:
                self.c.perform()
            except Exception as e:
                print('connection error:' + str(e))
                self.buffer.close()
                self.c.close()
    
        def getinfo(self):
            h1 = self.c.getinfo(pycurl.HTTP_CODE)  # 状态码
            h2 = self.c.getinfo(pycurl.TOTAL_TIME)  # 传输结束总消耗时间
            h3 = self.c.getinfo(pycurl.NAMELOOKUP_TIME)  # DNS解析时间
            h4 = self.c.getinfo(pycurl.CONNECT_TIME)  # 建立连接时间
            h5 = self.c.getinfo(pycurl.PRETRANSFER_TIME)  # 建立连接到准备传输消耗时间
            h6 = self.c.getinfo(pycurl.STARTTRANSFER_TIME)  # 从建立连接到传输开始消耗时间
            h7 = self.c.getinfo(pycurl.REDIRECT_TIME)  # 重定向消耗时间
            h8 = self.c.getinfo(pycurl.SIZE_UPLOAD)  # 上传数据包大小
            h9 = self.c.getinfo(pycurl.SIZE_DOWNLOAD)  # 下载数据包大小
            h10 = self.c.getinfo(pycurl.SPEED_DOWNLOAD)  # 平均下载速度
            h11 = self.c.getinfo(pycurl.SPEED_UPLOAD)  # 平均上传速度
            h12 = self.c.getinfo(pycurl.HEADER_SIZE)  # http头文件大小
            info ='''
                http状态码:%s
                传输结束总时间:%.2f ms
                DNS解析时间:%.2f ms
                建立连接时间:%.2f ms
                准备传输时间:%.2f ms
                传输开始时间:%.2f ms
                重定向时间:%.2f ms
                上传数据包大小:%d bytes/s
                下载数据包大小:%d bytes/s
                平均下载速度:%d bytes/s
                平均上传速度:%d bytes/s
                http头文件大小:%d byte
            ''' %(h1,h2*1000,h3*1000,h4*1000,h5*1000,h6*1000,h7*1000,h8,h9,h10,h11,h12)
            print(info)
            self.buffer.close()
            self.c.close()
    
    if __name__ == '__main__':
        curl_respon = ex_response("http://pycurl.io/")
        curl_respon.getinfo()

    例6:发送表单数据

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @Time    : 2018/6/6 12:23
    # @Author  : Py.qi
    # @File    : from_pycurl.py
    # @Software: PyCharm
    
    import pycurl
    from urllib.parse import urlencode
    
    c = pycurl.Curl()
    c.setopt(c.URL,'http://192.168.146.140/home/')
    post_data = {'username':'china','password':'7777','age':'18','salary':'999999'}
    postfields = urlencode(post_data)  #表单数据编码
    c.setopt(pycurl.POSTFIELDS,postfields) #POSTFIELDS自动以POST的方式提交并请求发送数据
    c.perform()
    c.close()

    例7:文件上传

    HTML表单中文件上传的行为,使用HTTPPOST选项,FORM_FILE指定文件路径。

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @Time    : 2018/6/6 13:22
    # @Author  : Py.qi
    # @File    : httppost_pycurl.py
    # @Software: PyCharm
    
    import pycurl
    
    c=pycurl.Curl()
    c.setopt(c.URL,'http://192.168.146.140/home/')
    #HTTPPOST选项是通过POST请求来执行文件上传,fileupload指定上传文件字段,使用c.FORM_FILE来指定文件位置
    c.setopt(c.HTTPPOST,[
        ('fileupload',(c.FORM_FILE,'/home/image.jpg',)),
    ]
    )
    c.perform()
    c.close()

    例8:使用FORM_FILENAME设置文件名,FORM_CONTENTTYPE指定文件内容类型,来调整文件名和类型上传文件

    import pycurl
    
    c = pycurl.Curl()
    c.setopt(c.URL, 'http://192.168.146.140/home/')
    
    c.setopt(c.HTTPPOST, [
        ('fileupload', (
             #指定文件路径
            c.FORM_FILE, __file__,
            # 设置文件名
            c.FORM_FILENAME, 'helloworld.py',
            # 设置文件类型
            c.FORM_CONTENTTYPE, 'application/x-python',
        )),
    ])
    
    c.perform()
    c.close()

    例9:内存中文件数据上传,使用BUFFER和BUFFERPTR

    import pycurl
    
    c = pycurl.Curl()
    c.setopt(c.URL, 'http://192.168.146.140/home/')
    
    c.setopt(c.HTTPPOST, [
        ('fileupload', (
            c.FORM_BUFFER, 'readme.txt',
            c.FORM_BUFFERPTR, 'This is a fancy readme file',
        )),
    ])
    
    c.perform()
    c.close()

    例10:直接通过物理文件排列进行上传

    import pycurl
    
    c = pycurl.Curl()
    c.setopt(c.URL, 'http://192.168.146.140/home/')
    
    c.setopt(c.UPLOAD, 1)
    file = open('body.json')  #读取文件
    c.setopt(c.READDATA, file)  #直接上传文件
    
    c.perform()
    c.close()
    
    file.close()

    例11:通过缓存数据上传

    import pycurl
    from io import BytesIO
    
    c = pycurl.Curl()
    c.setopt(c.URL, 'http://192.168.146.140/home/')
    
    c.setopt(c.UPLOAD, 1)
    data = '{"json":true}'
    #在缓存中读取的数据需要解码在python3中
    buffer = BytesIO(data.encode('utf-8'))
    c.setopt(c.READDATA, buffer)  #设置上传
    
    c.perform()
    c.close()

    ---------------------------------------------------------------------------------------------end

  • 相关阅读:
    解决PKIX:unable to find valid certification path to requested target 的问题
    Linux 上的常用文件传输方式介绍与比较
    用VNC远程图形化连接Linux桌面的配置方法
    红帽中出现”This system is not registered with RHN”的解决方案
    linux安装时出现your cpu does not support long mode的解决方法
    CentOS SSH配置
    es6扩展运算符及rest运算符总结
    es6解构赋值总结
    tortoisegit安装、clon、推送
    es6环境搭建
  • 原文地址:https://www.cnblogs.com/zhangxinqi/p/9136376.html
Copyright © 2011-2022 走看看