最近需要对节点到源站自己做个监控,简单的ping可以检测到一些东西,但是http请求的检查也要进行,于是就研究了下pycurl
pycurl是个用c语言实现的python 库,虽然据说不是那么pythonic,但是却很高效,它支持的协议居多:

supporting FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE and LDAP. libcurl supports HTTPS certificates, HTTP POST, HTTP PUT, FTP uploading, kerberos, HTTP form based upload, proxies, cookies, user+password authentication, file transfer resume, http proxy tunneling and more!

这一堆协议已经很多了,我需要就是http一个,相对urlib来说,这个库可能更快些。

以下这个脚本是对某一个给定的url进行检查,并打印出http相应码,响应大小,建立连接时间,准备传输时间,传输第一个字节时间,完成时间

#!/usr/bin/python

# coding: UTF-8

import StringIO

import pycurl

import sys

import os

class Test:

def __init__(self):

self.contents = ''

def body_callback(self,buf):

self.contents = self.contents + buf

def test_gzip(input_url):

t = Test()

#gzip_test = file("gzip_test.txt", 'w')

c = pycurl.Curl()

c.setopt(pycurl.WRITEFUNCTION,t.body_callback)

c.setopt(pycurl.ENCODING, 'gzip')

c.setopt(pycurl.URL,input_url)

c.perform()

http_code = c.getinfo(pycurl.HTTP_CODE)

http_conn_time =  c.getinfo(pycurl.CONNECT_TIME)

http_pre_tran =  c.getinfo(pycurl.PRETRANSFER_TIME)

http_start_tran =  c.getinfo(pycurl.STARTTRANSFER_TIME)

http_total_time = c.getinfo(pycurl.TOTAL_TIME)

http_size = c.getinfo(pycurl.SIZE_DOWNLOAD)

print 'http_code http_size conn_time pre_tran start_tran total_time'

print "%d %d %f %f %f %f"%(http_code,http_size,http_conn_time,http_pre_tran,http_start_tran,http_total_time)

if __name__ == '__main__':

input_url = sys.argv[1]

test_gzip(input_url)

脚本运行效果

xu:~/curl$ python pycurl_test.py http://daxuxu.info/

http_code http_size conn_time pre_tran start_tran total_time

200 8703 0.748147 0.748170 1.632642 1.636552

pycurl 的一些响应信息:
(参考: http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html )

pycurl.NAMELOOKUP_TIME 域名解析时间
pycurl.CONNECT_TIME 远程服务器连接时间
pycurl.PRETRANSFER_TIME 连接上后到开始传输时的时间
pycurl.STARTTRANSFER_TIME 接收到第一个字节的时间
pycurl.TOTAL_TIME 上一请求总的时间
pycurl.REDIRECT_TIME 如果存在转向的话,花费的时间

pycurl.EFFECTIVE_URL
pycurl.HTTP_CODE HTTP 响应代码
pycurl.REDIRECT_COUNT 重定向的次数
pycurl.SIZE_UPLOAD 上传的数据大小
pycurl.SIZE_DOWNLOAD 下载的数据大小
pycurl.SPEED_UPLOAD 上传速度
pycurl.HEADER_SIZE 头部大小
pycurl.REQUEST_SIZE 请求大小
pycurl.CONTENT_LENGTH_DOWNLOAD 下载内容长度
pycurl.CONTENT_LENGTH_UPLOAD 上传内容长度
pycurl.CONTENT_TYPE 内容的类型
pycurl.RESPONSE_CODE 响应代码
pycurl.SPEED_DOWNLOAD 下载速度
pycurl.SSL_VERIFYRESULT
pycurl.INFO_FILETIME 文件的时间信息

pycurl.HTTP_CONNECTCODE HTTP 连接代码
pycurl.HTTPAUTH_AVAIL
pycurl.PROXYAUTH_AVAIL
pycurl.OS_ERRNO
pycurl.NUM_CONNECTS
pycurl.SSL_ENGINES
pycurl.INFO_COOKIELIST
pycurl.LASTSOCKET
pycurl.FTP_ENTRY_PATH

########################################################

前几天看完《Python简明教程》,预想练手,想起同事的一个 ruby 代码,尝试改写成 python,顺便看看两个语言的简练程度。下面是原始的 ruby 代码:

  #!/usr/bin/env ruby

require 'rubygems'
require 'net/http'

urls = ["http://icyleaf.com"]
.times do
  urls.each do |url|
    start_at = Time.now
    Net::HTTP.get URI.parse(url)
    end_at = Time.now
    diff = end_at - start_at
    if diff <</span> . then
      color_code =
    elsif diff > . then
      color_code =
    else
      color_code =
    end
    puts "#{url}\n time: \033[#{color_code}m#{diff}\033[0m seconds"
  end
end

改写 python 的同时,考虑脚本的灵活性准备增加两个参数,第一个是请求测试次数,第二个是请求测试的 URL,而 python 默认提供了argparse 库,可以很方便的生成 --help 的帮助和解析传递的参数:

 

#!/usr/bin/env python

import urllib2
import time
import sys
import argparse

def benchmark(url, count):
    for i in range(count):
        s = time.time()
        r = urllib2.urlopen(urllib2.Request(url))
        e = time.time()
        diff = e - s

if diff <</span> 0.3:
            color_code =
        elif diff > 0.8:
            color_code =
        else:
            color_code =

print '# %d' % (i + )
        print '\tStauts: %s' % r.getcode()
        print '\tTime: \033[%dm%f\033[0m second(s)' % (color_code, diff)

def main(argv):
    parser = argparse.ArgumentParser(description='url request time test')

parser.add_argument('URL', help='request url')
    parser.add_argument('-t', '--time', action='store', dest='count', type=int, default=, help='request times')
    args = parser.parse_args(argv)

benchmark(args.URL, args.count)

if __name__ == '__main__':
    main(sys.argv[:])

当然,我主要是为了练手 python 才去写的,ruby 本身也有 optparse 库用于解析参数,但是需要自己手写生成 --help 的输出,而且需要对每个参数做相应的 callback。

效果如下:

Posted by icyleaf on 2012-08-02

#########################################################

用Python编一个抓网页的程序是非常快的,下面就是一个例子:

 

importurllib2

html=urllib2.urlopen('http://www.server110.com').read()

但是在实际工作中,这种写法是远远不够的,至少会遇到下面几个问题:

网络会出错,任何错误都可能。例如机器宕了,网线断了,域名出错了,网络超时了,页面没有了,网站跳转了,服务被禁了,主机负载不够了…

服务器加上了限制,只让常见浏览器访问

服务器加上了防盗链的限制

某些2B网站不管你HTTP请求里有没有Accept-Encoding头部,也不管你头部具体内容是什么,反正总给你发gzip后的内容

URL链接千奇百怪,带汉字的也罢了,有的甚至还有回车换行

某些网站HTTP头部里有一个Content-Type,网页里有好几个Content-Type,更过分的是,各个Content-Type还不一样,最过分的是,这些Content-Type可能都不是正文里使用的Content-Type,从而导致乱码

网络链接很慢,乘分析几千个页面的时间,建议你可以好好吃顿饭去了

Python本身的接口有点糙

好吧,这么一大箩筐问题,我们来一个个搞定。

错误处理和服务器限制

首先是错误处理。由于urlopen本身将大部分错误,甚至包括4XX和5XX的HTTP响应,也搞成了异常,因此我们只需要捕捉异常就好了。同时,我们也可以获取urlopen返回的响应对象,读取它的HTTP状态码。除此之外,我们在urlopen的时候,也需要设置timeout参数,以保证处理好超时。下面是代码示例:

importurllib2

importsocket

try:

f=urllib2.urlopen('http://www.server110.com',timeout=10)

code=f.getcode()

ifcode<</span>200orcode>=300:

#你自己的HTTP错误处理

exceptException,e:

ifisinstance(e,urllib2.HTTPError):

print'http error: {0}'.format(e.code)

elifisinstance(e,urllib2.URLError)andisinstance(e.reason,socket.timeout):

print'url error: socket timeout {0}'.format(e.__str__())

else:

print'misc error: '+e.__str__()

如果是服务器的限制,一般来说我们都可以通过查看真实浏览器的请求来设置对应的HTTP头部,例如针对浏览器的限制我们可以设置User-Agent头部,针对防盗链限制,我们可以设置Referer头部,下面是示例代码:

 

importurllib2

req=urllib2.Request('http://www.server110.com',

headers={"Referer":"http://www.baidu.com",

"User-Agent":"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.68 Safari/534.24"

})

html=urllib2.urlopen(url=req,timeout=10).read()

有的网站用了Cookie来限制,主要是涉及到登录和限流,这时候没有什么通用的方法,只能看能否做自动登录或者分析Cookie的问题了。

URL与内容处理

URL里奇形怪状的格式只能个别分析,个别处理,逮到一个算一个。例如针对URL里可能有汉字,相对路径,以及回车换行之类的问题,我们可以先用urlparse模块的urljoin函数处理相对路径的问题,然后去掉乱七八糟的回车换行之类的玩意,最后用urllib2的quote函数处理特殊字符编码和转义的问题,生成真正的URL。

当然,在使用的过程中你会发现Python的urljoin和urlopen都有些问题,因此具体的代码我们在后面再给。

对于那些不管三七二十一就把gzip内容丢过来的,我们直接分析它的内容格式,不要管HTTP头部就好了。代码是这样的:

 

importurllib2

importgzip,cStringIO

html=urllib2.urlopen('http://www.server110.com').read()

ifhtml[:6]=='\x1f\x8b\x08\x00\x00\x00':

html=gzip.GzipFile(fileobj=cStringIO.StringIO(html)).read()

Python使用pycurl获取http的响应时间的更多相关文章

  1. python执行shell获取硬件参数写入mysql

    最近要获取服务器各种参数,包括cpu.内存.磁盘.型号等信息.试用了Hyperic HQ.Nagios和Snmp,它们功能都挺强大的,但是于需求不是太符,亦或者太heavy. 于是乎想到用python ...

  2. 运用Python语言编写获取Linux基本系统信息(三):Python与数据库编程,把获取的信息存入数据库

    运用Python语言编写获取Linux基本系统信息(三):Python与数据库编程 有关前两篇的链接: 运用Python语言编写获取Linux基本系统信息(一):获得Linux版本.内核.当前时间 运 ...

  3. 运用Python语言编写获取Linux基本系统信息(二):文件系统使用情况获取

    本文跟着上一篇文章继续写,上一篇文章的链接 运用Python语言编写获取Linux基本系统信息(一):获得Linux版本.内核.当前时间 一.随便说说 获取文件系统使用情况的思路和上一篇获取主要系统是 ...

  4. Python 通过脚本获取Android的apk的部分属性,再通过加密算法生成秘钥。

    Python 通过脚本获取Android的apk的部分属性,再通过加密算法生成秘钥. #!/usr/bin/env python # -*- coding: utf- -*- import os im ...

  5. python使用traceback获取详细的异常信息

    原创来自:https://blog.csdn.net/mengtao0609/article/details/55049059 python使用traceback获取详细的异常信息 2017年02月1 ...

  6. Python 之自动获取公网IP

    Python 之自动获取公网IP 2017年9月30日 文档下载:https://wenku.baidu.com/view/ff40aef7f021dd36a32d7375a417866fb84ac0 ...

  7. Python中如何获取类属性的列表

    这篇文章主要给大家介绍了在Python中如何获取类属性的列表,文中通过示例代码介绍的很详细,相信对大家的学习或者工作具有一定的参考借鉴价值,有需要的朋友可以参考借鉴,下面来一起看看吧. 前言 最近工作 ...

  8. python开发_tkinter_获取文本框内容_给文本框添加键盘输入事件

    在之前的blog中有提到python的tkinter中的菜单操作 python开发_tkinter_窗口控件_自己制作的Python IDEL_博主推荐 python开发_tkinter_窗口控件_自 ...

  9. Python+selenium之获取文本值和下拉框选择数据

    Python+selenium之获取文本值和下拉框选择数据 一.结合实例进行描述 1. 实例如下所示: #新增标签操作 def func_labels(self): self.driver.find_ ...

随机推荐

  1. 一些Java面试题深入分析

    一.&和&&的差别? &和&&都能够用作逻辑与的运算符.表示逻辑与(and),当运算符两边的表达式的结果都为true时.整个运算结果才为true,否则, ...

  2. 【Oracle】PL/SQL Developer 快捷键、使用技巧

    1.类SQL PLUS窗口:File->New->Command Window,这个类似于oracle的客户端工具sql plus,但比它好用多了. 2.设置关键字自动大写:Tools-& ...

  3. gdb调试运行程序带参数(调用动态链接库),debug过程记录

    library多线程file1.gdb (运行程序名称) 例如 gdb cbenchmark 2.设置运行参数 set args -c 1 -n 1 -F ./libaliww.so -l 1 3.如 ...

  4. 卡特兰数(Catalan数)

    首先奉上高中的排列组合公式,防止某些人忘记了 卡特兰数: 规定h(0)=1,而h(1)=1,h(2)=2,h(3)=5,h(4)=14,h(5)=42,h(6)=132,h(7)=C(14,7)-C( ...

  5. 火狐浏览器(firefox)中js要注意的问题

    1.出现错误调用error方法或者ajax请求了多次,那么极有可能是异步请求的原因. 添加   async  : false  , -> async. 默认是 true,即为异步方式,$.aja ...

  6. POJ 2750 Potted Flower (单点改动求线段树上最大子序列和)

    题目大意: 在一个序列上每次改动一个值,然后求出它的最大的子序列和. 思路分析: 首先我们不考虑不成环的问题.那就是直接求每一个区间的最大值就好了. 可是此处成环,那么看一下以下例子. 5 1 -2 ...

  7. vsftpd問題集

    vsftpd无法看到文件:226 Transfer done (but failed to open directory). 原因:目录不是一个 world_readable目录 解决方法:在配置文件 ...

  8. CXSprite.cpp文件

    #include "XSprite.h" CXSprite::CXSprite(void) { m_strPic.clear(); } CXSprite::~CXSprite() ...

  9. java线程阻塞问题排查方法

    我开发的worker,每隔几个月线上都会阻塞一次,一直都没查出问题.今天终于了了这个心结.把解决过程总结下和大家分享. 首先用jstack命令打出这个进程的全部线程堆栈.拿到线程dump文件之后,搜索 ...

  10. C++static关键字用法

    一.static的作用有三种:限制变量或函数作用域.保持变量内容的持久.默认初始化为0 1.被static关键字修饰的全局函数或者变量具有文件作用域,即只在当前文件中可见. 2.被static修饰的变 ...