您的位置:首页 > 理论基础 > 计算机网络

获取http响应时间,pycurl,python

2017-09-14 11:54 483 查看
转载自:http://blog.sina.com.cn/s/blog_603e2b9f0102eu7e.html


获取http响应时间,pycurl,python

最近需要对节点到源站自己做个监控,简单的ping可以检测到一些东西,但是http请求的检查也要进行,于是就研究了下pycurl

pycurl是个用c语言实现的python 库,虽然据说不是那么pythonic,但是却很高效,它支持的协议居多:
supporting FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE andLDAP. libcurl supports HTTPS certificates, HTTP POST, HTTP PUT, FTPuploading, kerberos, HTTP form based upload, proxies, cookies,user+password authentication, file transfer resume, http proxytunneling
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.t
18dec
xt", '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_codehttp_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_trantotal_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

 

########################################################
http://icyleaf.com/2012/08/url-request-time-test-using-python-with-argparse
前几天看完《Python简明教程》,预想练手,想起同事的一个ruby 代码,尝试改写成 python,顺便看看两个语言的简练程度。下面是原始的 ruby 代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22


#!/usr/bin/env ruby

require 'rubygems'
require 'net/http'

urls = ["http://icyleaf.com"]
50.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> 0.3 then
color_code = 32
elsif diff > 0.8 then
color_code = 31
else
color_code = 33
end
puts "#{url}\n time: \033[#{color_code}m#{diff}\033[0m seconds"
end
end


改写 python的同时,考虑脚本的灵活性准备增加两个参数,第一个是请求测试次数,第二个是请求测试的 URL,而 python默认提供了argparse 库,可以很方便的生成--help 的帮助和解析传递的参数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2223
24
25
26
27
28
29
30
31
32
33
34
35
36


#!/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 = 32
elif diff > 0.8:
color_code = 31
else:
color_code = 33

print '# %d' % (i + 1)
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=10, help='request times')
args = parser.parse_args(argv)

benchmark(args.URL, args.count)

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


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



Posted by icyleaf on 2012-08-02

 

 

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

 
http://blog.raphaelzhang.com/2012/03/issues-in-python-crawler/


用Python抓网页的注意事项

3条回复

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

 

1
2
3

importurllib2
 
html=urllib2.urlopen('http://blog.raphaelzhang.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参数,以保证处理好超时。下面是代码示例:
 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

importurllib2
importsocket
 
try:
  f=urllib2.urlopen('http://blog.raphaelzhang.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: sockettimeout {0}'.format(e.__str__())
  else:
    print'misc error:'+e.__str__()

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

 

1
2
3
4
5
6
7

importurllib2
 
req=urllib2.Request('http://blog.raphaelzhang.com',
  headers={"Referer":"http://www.baidu.com",
    "User-Agent":"Mozilla/5.0
(WindowsNT 5.1) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.68Safari/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头部就好了。代码是这样的:
 

 

1
2
3
4
5
6

importurllib2
importgzip,cStringIO
 
html=urllib2.urlopen('http://blog.raphaelzhang.com').read()
ifhtml[:6]=='\x1f\x8b\x08\x00\x00\x00':
  html=gzip.GzipFile(fileobj=cStringIO.StringIO(html)).read()

添加 requests模块自带响应时间函数import requests r = requests.get("http://bitest.hylinkad.com")print r.elapsed.microsecondsmicroseconds,seconds,total_secondselapsed是datetime.timedelta类型。total_seconds=seconds+microsecondstotal_seconds是整个请求耗费的时间。seconds是请求耗费时间的秒数,microseconds是微妙数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python http