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()
运行结果: