python之第三方库pycurl库:PycURl是一个C语言写的libcurl的python绑定库。libcurl 是一个自由的,并且容易使用的用在客户端的 URL 传输库。

前言

1、 pycurl 库是功能强大的python的url库,是用c语言写的,速度很快,比urllib和httplib都快。支持操作协议有FTP, HTTP,HTTPS,TELNET等,通过pycurl提供的方法,可以实现探测WEB服务质量的情况,比如,响应的HTTP状态码、请求延时、HTTP头信息、下载速度等。

2、pycurl官方网站:pycurl 官方

3、pycurl 是  libcurl 的Python接口。 pycurl 可用于从 Python 程序中获取由 URL 标识的对象,类似于 urllib Python 模块。 pycurl 模块成熟,速度非常快,并且支持很多特性。

4、libcurl 库是一个免费且易于使用的客户端 URL 传输库,支持 FTP、FTPS、HTTP、HTTPS、SCP、SFTP、TFTP、TELNET、DICT、LDAP、LDAPS、FILE、IMAP、SMTP、POP3 和 RTSP。libcurl 支持 SSL 证书、HTTP POST、HTTP PUT、FTP 上传、基于 HTTP 表单的上传、代理、cookie、用户+密码身份验证(Basic、Digest、NTLM、Negotiate、Kerberos4)、文件传输恢复、http 代理隧道等等。

5、 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 等...

6、libcurl 库是免费的、线程安全的、与 IPv6 兼容、功能丰富、支持良好、速度快、文档完整 ,并且已被许多知名、成功的大公司和众多应用程序使用。

7、pycurl 库的主要缺点是它是  libcurl  之上的一个相对薄的层,没有任何那些漂亮的 Pythonic 类层次结构。

安装

1、第一种方式(pip安装方式): 

[root@localhost ~]$ pip install pycurl

2、第二种方式(下载源码安装方式):

yum install libcurl-devel

wget https://curl.haxx.se/download/curl-7.61.0.tar.gz

tar -zxvf curl-7.61.0.tar.gz

cd curl-7.61.0/

./configure 

make && make install

export LD_LIBRARY_PATH=/usr/local/lib

3、测试 pycurl 库是否安装成功,命令行执行如下代码:

import pycurl
print(pycurl.version)

类与方法

1、 close() 方法:对应libcurl包中的curl_easy_cleanup方法,无参数,实现关闭,回收Curl对象。

2、 perform() 方法:对应libcurl包中的curl_easy_perform方法,无参数,实现Curl对象请求的提交。

3、 setopt(option, value) 方法:对应libcurl包中的curl_easy_setopt方法,参数option是通过libcurl的常量来指定的,参数value的值会依赖option,可以是一个字符串、整型,长整型,文件对象,列表或函数等。

c = pycurl.Curl()  # 创建一个curl对象

c.setopt(pycurl.CONNECTTIMEOUT, 5)  # 连接的等待时间,设置为0则不等待

c.setopt(pycurl.TIMEOUT, 5)  # 请求超时时间

c.setopt(pycurl.NOPROGRESS, 0)  # 是否屏蔽下载进度条,非0则屏蔽

c.setopt(pycurl.MAXREDIRS, 5)  # 指定HTTP重定向的最大数

c.setopt(pycurl.FORBID_REUSE, 1)  # 完成交互后强制断开连接,不重用

c.setopt(pycurl.FRESH_CONNECT, 1)  # 强制获取新的连接,即替代缓存中的连接

c.setopt(pycurl.DNS_CACHE_TIMEOUT, 60)  # 设置保存DNS信息的时间,默认为120秒

c.setopt(pycurl.URL, "http://www.baidu.com")  # 指定请求的URL

c.setopt(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

c.setopt(pycurl.HEADERFUNCTION, getheader)  # 将返回的HTTP HEADER定向到回调函数getheader

c.setopt(pycurl.WRITEFUNCTION, getbody)  # 将返回的内容定向到回调函数getbody

c.setopt(pycurl.WRITEHEADER, fileobj)  # 将返回的HTTP HEADER定向到fileobj文件对象

c.setopt(pycurl.WRITEDATA, fileobj)  # 将返回的HTML内容定向到fileobj文件对象
c.setopt(pycurl.VERBOSE, 1) # 是否在控制台上显示请求URL的请求头和响应头信息

4、 getinfo(option) 方法:对应libcurl包中的curl_easy_getinfo方法,参数option是通过libcurl的常量来指定的。

c = pycurl.Curl()  # 创建一个curl对象

c.getinfo(pycurl.HTTP_CODE)  # 返回的HTTP状态码

c.getinfo(pycurl.TOTAL_TIME)  # 传输结束所消耗的总时间

c.getinfo(pycurl.NAMELOOKUP_TIME)  # DNS解析所消耗的时间

c.getinfo(pycurl.CONNECT_TIME)  # 建立连接所消耗的时间

c.getinfo(pycurl.PRETRANSFER_TIME)  # 从建立连接到准备传输所消耗的时间

c.getinfo(pycurl.STARTTRANSFER_TIME)  # 从建立连接到传输开始消耗的时间

c.getinfo(pycurl.REDIRECT_TIME)  # 重定向所消耗的时间

c.getinfo(pycurl.SIZE_UPLOAD)  # 上传数据包大小

c.getinfo(pycurl.SIZE_DOWNLOAD)  # 下载数据包大小

c.getinfo(pycurl.SPEED_DOWNLOAD)  # 平均下载速度

c.getinfo(pycurl.SPEED_UPLOAD)  # 平均上传速度

c.getinfo(pycurl.HEADER_SIZE)  # HTTP头部大小

 经典应用

1、探索web服务质量

HTTP服务是最流行的互联网应用之一,服务质量的好坏关系到用户体验以及网站的运营服务水平,最常用的有两个标准:

  • 一为服务的可用性,比如是否处于正常提供服务状态,而不是出现404页面或500页面错误等;
  • 二是服务响应的速度,比如静态类文件下载时间都控制在毫秒级,动态CGI为秒级。

本实例使用 pycurl 模块的 setopt 与 getinfo 方法实现对HTTP服务质量的探测,获取监控URL返回的HTTP状态码,HTTP状态码采用 pycurl.HTTP_CODE 常量,以及从HTTP请求到下载期间各环节的响应时间,通过 pycurl.NAMELOOKUP_TIME 、 pycurl.CONNECT_TIME 、 pycurl.PRETRANSFER_TIME 、 pycurl.R 等常量来时间。另外通过 pycurl.WRITEHEADER 、 pycurl.WRITEDATA 常量得到目标URL的HTTP响应头部及页面内容。

第一种方法:

#!/usr/bin/python
# -*- coding:UTF-8 -*-
import os
import sys

import pycurl

# 探测的目标URL
URL = "http://www.baidu.com"
# 创建一个Curl对象
c = pycurl.Curl()

# 定义请求的URL常量
c.setopt(pycurl.URL, URL)
# 定义请求连接的等待时间
c.setopt(pycurl.CONNECTTIMEOUT, 5)
# 定义请求超时时间
c.setopt(pycurl.TIMEOUT, 5)
# 屏蔽下载进度条
c.setopt(pycurl.NOPROGRESS, 1)
# 完成交互后强制断开连接,不重用
c.setopt(pycurl.FORBID_REUSE, 1)
# 指定HTTP重定向的最大数为1
c.setopt(pycurl.MAXREDIRS, 1)
# 设置保存DNS信息的时间为30秒
c.setopt(pycurl.DNS_CACHE_TIMEOUT, 30)
# 创建一个文件对象,以“wb”方式打开,用来存储返回的http头部及页面内容
indexfile = open(os.path.dirname(os.path.realpath(__file__)) + "/content.txt", "wb")
# 将返回的HTTP HEADER定向到indexfile文件
c.setopt(pycurl.WRITEHEADER, indexfile)
# 将返回的HTML内容定向到indexfile文件对象
c.setopt(pycurl.WRITEDATA, indexfile)
try:
    # 提交请求
    c.perform()
except Exception as e:
    print("connection error: " + str(e))
    indexfile.close()
    c.close()
    sys.exit()

# 获取DNS解析时间
NAMELOOKUP_TIME = c.getinfo(c.NAMELOOKUP_TIME)
# 获取建立连接时间
CONNECT_TIME = c.getinfo(c.CONNECT_TIME)
# 获取从建立连接到准备传输所消耗的时间
PRETRANSFER_TIME = c.getinfo(c.PRETRANSFER_TIME)
# 获取从建立连接到传输开始消耗的时间
STARTTRANSFER_TIME = c.getinfo(c.STARTTRANSFER_TIME)
# 获取传输的总时间
TOTAL_TIME = c.getinfo(c.TOTAL_TIME)
# 获取HTTP状态码
HTTP_CODE = c.getinfo(c.HTTP_CODE)
# 获取下载数据包大小
SIZE_DOWNLOAD = c.getinfo(c.SIZE_DOWNLOAD)
# 获取HTTP头部大小
HEADER_SIZE = c.getinfo(c.HEADER_SIZE)
# 获取平均下载速度
SPEED_DOWNLOAD = c.getinfo(c.SPEED_DOWNLOAD)
# 打印输出相关数据
print("HTTP状态码: %d" % (HTTP_CODE))
print("DNS解析时间: %.2f ms" % (NAMELOOKUP_TIME * 1000))
print("建立连接时间: %.2f ms" % (CONNECT_TIME * 1000))
print("准备传输时间: %.2f ms" % (PRETRANSFER_TIME * 1000))
print("传输开始时间: %.2f ms" % (STARTTRANSFER_TIME * 1000))
print("传输结束总时间: %.2f ms" % (TOTAL_TIME * 1000))
print("下载数据包大小: %d bytes/s" % (SIZE_DOWNLOAD))
print("HTTP头部大小: %d byte" % (HEADER_SIZE))
print("平均下载速度: %d bytes/s" % (SPEED_DOWNLOAD))
# 关闭文件及Curl对象 indexfile.close() c.close()

运行结果:

content.txt文件内容(存储请求URL返回的http响应头部及页面内容)

第二种方法:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys

import pycurl
from past.builtins import raw_input


def get_info(url):
    """
    :param url:用户输入需要检测的URL地址
    info 字典主要用于映射dic字典
    dic字典主要存下curl结果
    :return:没return,直接print,函数可以改写,可以用于定时检测多个域名,增加一个需要检测的url列表即可
    """
    c = pycurl.Curl()
    c.setopt(pycurl.URL, url)  # 定义请求的URL常量
    c.setopt(pycurl.CONNECTTIMEOUT, 5)  # 请求等待时间最多5秒
    c.setopt(pycurl.TIMEOUT, 5)  # 定义请求超时时间(服务器没回应)
    c.setopt(pycurl.NOPROGRESS, 1)  # 屏蔽下载进度条
    c.setopt(pycurl.FORBID_REUSE, 1)  # 交互完成后强制断开连接,不重用
    c.setopt(pycurl.MAXREDIRS, 1)  # 指定HTTP重定向的最大数为1
    c.setopt(pycurl.DNS_CACHE_TIMEOUT, 30)  # 设置DNS信息保存时间为30秒
    c.setopt(pycurl.USERAGENT,
             "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 OPR/40.0.2308.81 (Edition Baidu)")
    dic = {}
    info = {
        'NAMELOOKUP_TIME': 'DNS解析时间',
        'CONNECT_TIME': '建立连接时间',
        'PRETRANSFER_TIME': '建立到准备传输所消耗的时间',
        'STARTTRANSFER_TIME': '建立连接到传输开始消耗的时间',
        'TOTAL_TIME': '传输总时间',
        'HTTP_CODE': 'HTTP状态码',
        'SIZE_DOWNLOAD': '下载数据包大小',
        'HEADER_SIZE': 'HTTP头部大小',
        'SPEED_DOWNLOAD': '平均下载速度'
    }
    with open(os.path.dirname(os.path.realpath(__file__)) + "/content.txt", "wb") as index_file:
        c.setopt(pycurl.WRITEHEADER, index_file)  # 将返回的HTTP HEADER定向到index_file文件对象
        c.setopt(pycurl.WRITEDATA, index_file)  # 将返回的HTML内容定向到index_file文件对象
        try:
            c.perform()
        except Exception as e:
            print("Connection error:" + str(e))
            c.close()
            sys.exit()
        dic['NAMELOOKUP_TIME'] = '%.2f ms' % (c.getinfo(c.NAMELOOKUP_TIME) * 1000)  # 获取DNS解析时间
        dic['CONNECT_TIME'] = '%.2f ms' % (c.getinfo(c.CONNECT_TIME) * 1000)  # 获取建立连接时间
        dic['PRETRANSFER_TIME'] = '%.2f ms' % (c.getinfo(c.PRETRANSFER_TIME) * 1000)  # 获取从建立到准备传输所消耗的时间
        dic['STARTTRANSFER_TIME'] = '%.2f ms' % (c.getinfo(c.STARTTRANSFER_TIME) * 1000)  # 获取从建立连接到传输开始消耗的时间
        dic['TOTAL_TIME'] = '%.2f ms' % (c.getinfo(c.TOTAL_TIME) * 1000)  # 获取传输总时间
        dic['HTTP_CODE'] = c.getinfo(c.HTTP_CODE)  # 获取HTTP状态码
        dic['SIZE_DOWNLOAD'] = '%d bytes/s' % (c.getinfo(c.SIZE_DOWNLOAD))  # 获取下载数据包大小
        dic['HEADER_SIZE'] = '%d bytes/s' % (c.getinfo(c.HEADER_SIZE))  # 获取HTTP头部大小
        dic['SPEED_DOWNLOAD'] = '%d bytes/s' % (c.getinfo(c.SPEED_DOWNLOAD))  # 获取平均下载速度
    for key in info:
        print(info[key], ':', dic[key])


def main():
    while True:
        URL = raw_input("请输入一个URL地址(Q for exit):")
        if URL.lower() == 'q':
            sys.exit()
        else:
            get_info(URL)


if __name__ == '__main__':
    main()

运行结果:

2、HTTP GET操作

import pycurl

PYCURL_CONNECTTIMEOUT = 30
PYCURL_TIMEOUT = 300
PYCURL_DOWNLOADURL = "http://www.baidu.com"
PYCURL_DOWNLOAD_FILE = "download.file"

fp = open(PYCURL_DOWNLOAD_FILE, 'wb+')


def pycurl_writeFile(buffer):
    fp.write(buffer)


def pycurl_download(url):
    # 全局初始化
    pycurl.global_init(pycurl.GLOBAL_ALL)

    # 实例化对象
    c = pycurl.Curl()

    # 参数设置
    c.setopt(pycurl.URL, url)
    c.setopt(pycurl.WRITEDATA, fp)
    c.setopt(pycurl.WRITEFUNCTION, pycurl_writeFile)
    c.setopt(pycurl.NOPROGRESS, 0)
    c.setopt(pycurl.CONNECTTIMEOUT, PYCURL_CONNECTTIMEOUT)
    c.setopt(pycurl.TIMEOUT, PYCURL_TIMEOUT)
    c.setopt(pycurl.VERBOSE, 1)

    # 执行
    try:
        c.perform()
    except Exception as e:
        print(e)

    # 资源回收
    c.close()
    fp.close()


if __name__ == '__main__':
    pycurl_download(PYCURL_DOWNLOADURL)

运行结果:

3、HTTP POST操作

首先搭建一个web服务:

再使用 pycurl 库构建请求post服务的代码:

import pycurl
import json

URL = "http://127.0.0.1:5000/ProcessPOSTJSON"

c = pycurl.Curl()
c.setopt(pycurl.URL, URL)
c.setopt(pycurl.HTTPHEADER, ['Content-Type: application/json'])
data = json.dumps({"name": "xgx", "sex": "male", "country": "china"})
print(data, type(data))
c.setopt(pycurl.POST, 1)
c.setopt(pycurl.POSTFIELDS, data)
c.setopt(pycurl.VERBOSE, 1)
c.perform()
c.close()

运行结果:

 

posted @ 2022-04-15 17:35  习久性成  阅读(587)  评论(0编辑  收藏  举报