1、Pycurl 的简单使用与对比在几次莫名其妙的退出之后,我终于有点放弃 urllib2,开始尝试其他的模块。看到很多人推荐 wget 和 pycurl。wget 是独立软件,所以就没考虑。pycurl 的话,得益于基于 c 语言开发的 curl 性能强劲,使得普遍反映它效率快、稳定性高、功能强大。于是决定尝试之,简单测试了下(见后面),如果用平均值来比较的话,pycur 所消耗的时间远小于 urllib2。这对于爬虫来讲,累积之后变化就非常可观了。PycURL 是一个非常快速(参考多并发操作)和丰富完整特性的,但是有点复杂的接口。如果你需要些简单或纯 Python 的模块,你可以参考一下 ur
2、llib2 或 urlgrabber 。通过 http:/ 了解 PycURL 的文档信息及其其他信息。因为 PycURL 是对 libcurl 的一个封装,使用时还需要参考 libcurl 的文档(针对 C 的)。pycurl 的安装获取和安装 libcurl 非常简单,取决于您所运行的 Linux 版本,如果你也使用ubuntu,那只需要使用 ap-get 就可以轻松安装。$ sudo apt-get libcurl3$ sudo apt-get python-pycurl如果想查看下系统内 pycurl 版本信息可以:1 import pycurl2 pycurl.version3 li
3、bcurl/7.19.7 GnuTLS/2.8.5 zlib/1.2.3.3 libidn/1.15如上所示,我的系统里的 libcurl 是 7.19.7 的最新版本。pycurl 的使用:pycurl.Curl() - Curl object这个函数创建一个同 libcurl 中的 CURL 处理器相对应的 Curl 对象.Curl 对象自动的设置 CURLOPT_VERBOSE 为 0, CURLOPT_NOPROGRESS 为 1,提供一个默认的CURLOPT_USERAGENT 和设置 CURLOPT_ERRORBUFFER 指向一个私 有的错误缓冲区.pycurl.CurlMult
4、i() - CurlMulti object这个函数创建一个新的与 libcurl 中的 CURLM 处理器相 对应的 CurlMulti 对象.pycurl.CurlShare() - CurlShare object这个函数创建一个新的与 libcurl 中的 CURLSH 处理器 相对应的 CurlShare 对象.CurlShare 对 象可以在 Curl 对象上传递 SHARE 选项参数. 待续其中:Curl 对象具有以下方法:close() - None 对应的是 libcurl 中的 curl_easy_cleanup 方法.当 Curl 对象不再被引用时 pycurl 会自动调
5、用这个方法,但也可直接地调用这个方法.perform() - None 对应于 libcurl 中的 curl_easy_perform 方法.setopt(option, value) - None 对应于 libcurl 中的 curl_easy_setopt 方法, option 使用 libcurl 中的 CURLOPT_*常量来指定,只可惜 CURLOPT_前缀现在已经被去掉了.value 的数据类型依赖于 option,它可以是一个字符串,整型,长整型,文件对象,列表或是函数.Example usage:import pycurlc = pycurl.Curl()c.setopt(
6、pycurl.URL, “http:/www.python.org/“)c.setopt(pycurl.HTTPHEADER, “Accept:“)import StringIOb = StringIO.StringIO()c.setopt(pycurl.WRITEFUNCTION, b.write)c.setopt(pycurl.FOLLOWLOCATION, 1)c.setopt(pycurl.MAXREDIRS, 5)c.perform()print b.getvalue()getinfo(option) - Result 对应于 libcurl 中的 curl_easy_getinfo
7、 方法, option 同样使用 libcurl 中的 CURLOPT_*常量来指定,只可惜 CURLOPT_前缀现在已经被去掉了. Result 包含一个整数,浮点数或字符串,这都信赖于给定的option.getinfo 方法不能在 perform 方法未调用或完成之前进行调用.Example usage:import pycurlc = pycurl.Curl()c.setopt(pycurl.URL, “http:/“)c.setopt(pycurl.FOLLOWLOCATION, 1)c.perform()print c.getinfo(pycurl.HTTP_CODE), c.get
8、info(pycurl.EFFECTIVE_URL). 200 “http:/ - String 返回这个处理器中内部 libcurl 错误缓冲区的字符串表示.其他的就以后再翻译吧。urilib2 VS pycurl 的一个简单对比编码如下,就是取一批 url,然后分别用 urllib2 和 pycurl 的方法来获取页面内容,计算它们各自所消耗的时间。最后比较平均时间。我这跑了一下,相关的数据如下,大概 pycurl 能比 urllib2 减少 20%以上的消耗时间。1: urllib2 平均时间:0.379438, pycurl 平均时间:0.2792132: urllib2 平均时间:0
9、.568966, pycurl 平均时间:0.3952013: urllib2 平均时间:0.606843, pycurl 平均时间:0.4599654: urllib2 平均时间:0.381241, pycurl 平均时间:0.2396735: urllib2 平均时间:0.503715, pycurl 平均时间:0.5436006: urllib2 平均时间:0.291307, pycurl 平均时间:0.1884927: urllib2 平均时间:0.449666, pycurl 平均时间:0.299233相关代码如下:1: #coding=utf-82: import os3: imp
10、ort datetime as dt4: import time5: import urllib26: import pycurl7: import cStringIO as StringIO8: 9: 测试用程序,用于比较 pycurl 和 urllib2 效率10: 一只橘子 2010.12.0511: 12: 13: def fetch_url(menuurl = “):14: 从 url 获取目录页内容;返回返回页面内容字符串15: 使用 urllib2 来实现16: 17: the_page = “18: try:19: #下载页面20: req = urllib2.Request(
11、menuurl)21: req.add_header(User-Agent, Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12)22: #设置超时23: response = urllib2.urlopen(req, timeout = 30)24: the_page = response.read()25: except Exception, e:26: crawlerlog(“+fetch_url():Error4: %s; menuurl: %s“ % (e
12、, menuurl) 27: return the_page 28: 29: def fetch_url2(menuurl = “):30: 从 url 获取目录页内容;返回返回页面内容字符串31: 使用 pycurl 来实现32: 33: the_page = “34: try:35: #下载页面36: req = pycurl.Curl()37: req.setopt(pycurl.URL, menuurl)38: # 设置超时39: req.setopt(pycurl.TIMEOUT, 30)40: fp = StringIO.StringIO()41: req.setopt(pycur
13、l.WRITEFUNCTION, fp.write)42: req.setopt(pycurl.USERAGENT, Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12) 43: req.perform()44: the_page = fp.getvalue()45: except Exception, e:46: crawlerlog(“+fetch_url():Error555: %s; menuurl: %s“ % (e, menuurl) 47: retur
14、n the_page 48: 49: def crawlerlog(doc):50: 保存日志51: 52: logfile = u“./crawler_error.log“53: try:54: out = open(logfile, “a“)55: out.write(“ Time: %s %s n“ % (dt.datetime.now(), doc)56: except Exception,e:57: print “ Error: %s“ % e58: finally:59: out.close() 60: 61: def url_vs_curl():62: print “开始:“,d
15、t.datetime.now()63: import timeit64: link = http:/ http:/, http:/, http:/, http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/, http:/ http:/ http:/ http:/ http:/,
16、 http:/, http:/, http:/65: link +=http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/www.booksky.org/, http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http
17、:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/www.shigeku.org/, http:/ http:/ http:/ http:/ link +=http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/www.li- http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/, http:/ http:/ http:/www.goldlion-
18、http:/ http:/.hk/, http:/ http:/ http:/ http:/ http:/ http:/www.e- http:/ http:/ http:/ http:/ http:/, http:/ http:/www.k- http:/ http:/ http:/ http:/, http:/ http:/ http:/ http:/ http:/ http:/ http:/.hk/, http:/.hk/, http:/ http:/www.valentino.it/, http:/ http:/ http:/ http:/ http:/ http:/ http:/ h
19、ttp:/.hk/, http:/ http:/ http:/ http:/ http:/ http:/ http:/www.c- http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ htt
20、p:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/www.tjoy.biz/, http:/ http:/www.kose.co.jp/, http:/.hk/, http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/www
21、.aupres- http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/www.head- http:/ http:/ http:/ http:/www.china- http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/www.c- http:/ http:/ http:/ http:/ http:/ http:/www.wal- http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/
22、 http:/www.hitachi- http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ http:/ 67: t_url = #urllib2 每个 url 的消耗时间的列表68: t_curl = #pycurl 每个 url 的消耗时间的列表69: f = “./time.csv“ #保存相关
23、数据,供进一步分析70: inf = open(f,a)71: for index, each in enumerate(link):72: # urllib273: a = time.time()74: aa = fetch_url(each)75: b = time.time()76: # pycurl77: bb = fetch_url2(each)78: c = time.time()79: t_url.append(b-a)80: t_curl.append(c-b) 81: # 保存 urllib2 的数据82: sum_url=0 83: inf.write(“urllib2n“
24、)84: for each in t_url:85: inf.write(str(each)+“n“)86: sum_url += each87: inf.write(“nn“) 88: # 保存 pycurl 的数据89: inf.write(“pycurln“) 90: sum_curl = 0 91: for each in t_curl:92: inf.write(str(each)+“n“)93: sum_curl += each94: print “urllib2 平均时间:%f, pycurl 平均时间:%f“ % (sum_url*1.0/len(t_url), sum_cur
25、l*1.0/len(t_curl)95: inf.close()96: print “结束:“,dt.datetime.now() 97: 98: if _name_ = “_main_“:99: for i in xrange(7): 100: url_vs_curl()附相关资料:urllib2 是 python 的一个获取 url(Uniform Resource Locators,统一资源定址器)的模块。它用 urlopen 函数的形式提供了一个非常简洁的接口。这使得用各种各样的协议获取 url 成为可能。它同时 也提供了一个稍微复杂的接口来处理常见的状况-如基本的认证,cookies
26、,代理等等。这些都是由叫做 opener和 handler 的对象来处理的。urllib2 属于 python 内置模块。Libcurl (http:/curl.haxx.se/libcurl/)的介绍:libcurl 是免费而且易于使用的客户端的 URL 传输库,支持 FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE 和 LDAP。libcurl 支持 HTTPS 认证, HTTP POST, HTTP PUT, FTP 上传, kerberos, 基于 HTTP 表单的上传,代理,cookies,用户名+密码认证,文件传输恢复,http 代理封装等!libcurl 是高度可移植的,它在大量平台上都有构建和一致的工作,包括: Solaris, NetBSD, FreeBSD, OpenBSD, Darwin, HP-UX, IRIX, AIX, Tru64, Linux, Windows, Amigo, OS/2, BeOs, Mac OS X, Ultrix, QNX, OpenVMS, RISC OS, Novell NetWare, DOS 和更多libcurl 是免费、线程安全、IPv6 安全、特性丰富,良好支持和快速的。pycurl 官方地址 http:/ 官网上有各个版本的pycurl 和相关文档。