PycURL学习笔记

转自:http://blog.donews.com/limodou/archive/2005/11/28/641257.aspx

PycURL 是一个C语言写的 libcurl 的 Python 绑定库。libcurl 是一个自由的,并且容易使用的用在客户端的 URL 传输库。它的功能很强大,在PycURL  的主页上介绍的支持的功能有:

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!

那一大堆的协议已经让人惊喜了,特别是还有代理服务器和用户认证之类的功能。这个库相对于 urllib2 来说,它不是纯 Python 的,它是一个 C 库,但因此速度更快,但它不是很 pythonic ,学起来有些复杂。它在多种平台下都有移植,象 Linux , Mac, Windows, 和多种Unix。

我安装了一个,并且测试了一小段代码,是有些复杂,代码如下:

        import pycurl
        c = 
pycurl.Curl()
        c.setopt(pycurl.URL, ‘http://feeds.feedburner.com/solidot’)
        import StringIO
        b = StringIO.StringIO()
        c.setopt(pycurl.WRITEFUNCTION, b.write)
        c.setopt(pycurl.FOLLOWLOCATION, 1)
        c.setopt(pycurl.MAXREDIRS, 5)
#        c.setopt(pycurl.PROXY, ‘http://11.11.11.11:8080′)
#        c.setopt(pycurl.PROXYUSERPWD, ‘aaa:aaa’)
        c.perform()
        print b.getvalue()

上述代码将会把奇客(Solidot)的RSS抓下来。如果有代理服务器,那么修改一下注释的两行即可。在 PycURL 的主页上还有一个多线程抓取的例子,有兴趣的可以看一看。


1. PycURL

pycurl — A Python interface to the cURL library

Pycurl包是一个libcurl的Python接口.pycurl已经成功的在Python2.2到Python2.5版编译测试过了.

Libcurl 是一个支持FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE 和 LDAP的客户端URL传输库.libcurl也支持HTTPS认证,HTTP POST,HTTP PUT,FTP上传,代理,Cookies,基本身份验证,FTP文件断点继传,HTTP代理通道等等.

Libcurl提供的所有功能都可以通过pycurl接口来使用.接下来的子章节概述怎么使用pycurl接口,并且假定已经知道了libcurl如何工作的.libcurl如何工作的更多信息,请参考curl库的web页面(http://curl.haxx.se/libcurl/c/). Module Functionality

pycurl.global_init(option) ->None 选项是以下常量之一:pycurl.GLOBAL_SSL, pycurl.GLOBAL_WIN32, pycurl.GLOBAL_ALL, pycurl.GLOBAL_NOTHING, pycurl.GLOBAL_DEFAULT. 相应的是libcurl的 curl_global_init() 方法.

pycurl.global_cleanup() -> None 相应的是libcurl的curl_global_cleanup()方法.

pycurl.version 这是liburl当前版本的信息,相应的是liburl的curl_version()方法. 用法举例:

切换行号显示
   1 >>> import pycurl
   2 >>> pycurl.version
   3 'libcurl/7.12.3 OpenSSL/0.9.7e zlib/1.2.2.1 libidn/0.5.12'

pycurl.version_info() -> Tuple

相对应的是libcurl中的 curl_version_info() 方法. 返回一个序列信息就像liburl的curl_version_info()方法返回的 curl_version_info_data 结构化数据.

用法举例:

切换行号显示
   1 >>> import pycurl
   2 >>> pycurl.version_info()
   3 (2, '7.12.3', 461827, 'i586-pc-linux-gnu', 1565, 'OpenSSL/0.9.7e', 9465951,
   4 '1.2.2.1', ('ftp', 'gopher', 'telnet', 'dict', 'ldap', 'http', 'file',
   5 'https', 'ftps'), None, 0, '0.5.12')

pycurl.Curl() -> Curl object

这个函数创建一个同libcurl中的CURL处理器相对应的Curl对象.Curl对象自动的设置CURLOPT_VERBOSE为0, CURLOPT_NOPROGRESS为1,提供一个默认的CURLOPT_USERAGENT和设置CURLOPT_ERRORBUFFER指向一个私有的错误缓冲区.

pycurl.CurlMulti() -> CurlMulti object

这个函数创建一个新的与libcurl中的CURLM处理器相对应的CurlMulti对象.

pycurl.CurlShare() -> CurlShare object

这个函数创建一个新的与libcurl中的CURLSH处理器相对应的CurlShare对象.CurlShare对象可以在Curl对象上传递SHARE选项参数. [待续]

Trackback: http://tb.blog.youkuaiyun.com/TrackBack.aspx?PostId=2146079

Subsections # Curl objects # CurlMulti objects # CurlShare objects # Callbacks Curl Object

Curl对象具有以下方法:

close() -> None 对应的是libcurl中的curl_easy_cleanup方法.当Curl对象不再被引用时pycurl会自动调用这个方法,但也可直接地调用这个方法.

perform() -> None 对应于libcurl中的curl_easy_perform方法.

setopt(option, value) -> None 对应于libcurl中的curl_easy_setopt方法, option使用libcurl中的CURLOPT_*常量来指定,只可惜CURLOPT_前缀现在已经被去掉了.value的数据类型依赖于 option,它可以是一个字符串,整型,长整型,文件对象,列表或是函数.

用法举例:

切换行号显示
   1 import pycurl
   2 c = pycurl.Curl()
   3 c.setopt(pycurl.URL, "http://www.python.org/")
   4 c.setopt(pycurl.HTTPHEADER, ["Accept:"])
   5 import StringIO
   6 b = StringIO.StringIO()
   7 c.setopt(pycurl.WRITEFUNCTION, b.write)
   8 c.setopt(pycurl.FOLLOWLOCATION, 1)
   9 c.setopt(pycurl.MAXREDIRS, 5)
  10 c.perform()
  11 print b.getvalue()

getinfo(option) -> Result 对应于libcurl中的curl_easy_getinfo方法, option同样使用libcurl中的CURLOPT_*常量来指定,只可惜CURLOPT_前缀现在已经被去掉了. Result包含一个整数,浮点数或字符串,这都信赖于给定的option.getinfo方法不能在perform方法未调用或完成之前进行调用.

用法举例:

errstr() -> String 返回这个处理器中内部libcurl错误缓冲区的字符串表示. CurlMulti Object

CurlMulti对象具有以下方法:

close() -> None 对应于libcurl中的curl_multi_cleanup()方法.当CurlMulti对象不再被引用时pycurl会自动调用该方法,也可显示调用该方法.

perform() -> tuple of status and the number of active Curl objects 对应于libcurl中的curl_multi_perform()方法.

add_handle(Curl object) -> None 对应于libcurl中的curl_multi_add_handle()方法.这个方法添加一个有效的Curl对象到CurlMulti对象. 重要提示:add_handle没有隐式的增加对Curl对象的引用(因而也没有增加Curl对象的引用次数)

remove_handle(Curl object) -> None 对应于libcurl中的curl_multi_remove_handle()方法.这个方法从CurlMulti对象中移除一个现有的Curl对象. 重要提示:remove_handle不会隐式的移除Curl对象的引用(因而不会减少Curl对象的引用次数).

fdset() -> triple of lists with active file descriptors, readable, writeable, exceptions. 对应于libcurl中的curl_multi_fdset()方法.这个方法从CurlMulti对象中提取文件描述信息.返回的列表可以被用于select模块to poll for events.

用法举例:

切换行号显示
   1 import pycurl
   2 c = pycurl.Curl()
   3 c.setopt(pycurl.URL, "http://curl.haxx.se")
   4 m = pycurl.CurlMulti()
   5 m.add_handle(c)
   6 while 1:
   7     ret, num_handles = m.perform()
   8     if ret != pycurl.E_CALL_MULTI_PERFORM: break
   9 while num_handles:
  10     apply(select.select, m.fdset() + (1,))
  11     while 1:
  12         ret, num_handles = m.perform()
  13         if ret != pycurl.E_CALL_MULTI_PERFORM: break

select(timeout) -> number of ready file descriptors or -1 on timeout 这是一个有用的函数,它简化了fdest()和select模块的组合使用.

用法举例:

切换行号显示
   1 import pycurl
   2 c = pycurl.Curl()
   3 c.setopt(pycurl.URL, "http://curl.haxx.se")
   4 m = pycurl.CurlMulti()
   5 m.add_handle(c)
   6 while 1:
   7     ret, num_handles = m.perform()
   8     if ret != pycurl.E_CALL_MULTI_PERFORM: break
   9 while num_handles:
  10     ret = m.select(1.0)
  11     if ret == -1:  continue
  12     while 1:
  13         ret, num_handles = m.perform()
  14         if ret != pycurl.E_CALL_MULTI_PERFORM: break

info_read([max]) -> numberof queued messages, a list of successful objects, a list of failed objects 对应于libcurl中的curl_multi_info_read()方法.这个方法从多重栈中提取至多max个信息然后返回两个列表.第一个列表包含成功完成的操作第二个列表包含每一个失败的curl对象的<curl对象,curl错误代码,curl错误信息>序列. [待续]

PS:本文翻译自PycURL的官方网站:http://pycurl.sourceforge.net/doc/pycurl.html,如有转贴请注明ChumpKlutz原创翻译

Trackback: http://tb.blog.youkuaiyun.com/TrackBack.aspx?PostId=2146140

CurlShare Object

CurlShare对象具有以下方法:

setopt(option, value) -> None 对应于libcurl中的curl_share_setopt方法, option使用libcurl中的CURLOPT_*常量来指定,只可惜CURLOPT_前缀现在改成SH_了.通常value必须是 LOCK_DATA_COOKIE 或者说LOCK_DATA_DNS.

用法举例:

切换行号显示
   1 import pycurl
   2 curl = pycurl.Curl()
   3 s = pycurl.CurlShare()
   4 s.setopt(pycurl.SH_SHARE, pycurl.LOCK_DATA_COOKIE)
   5 s.setopt(pycurl.SH_SHARE, pycurl.LOCK_DATA_DNS)
   6 curl.setopt(pycurl.URL, 'http://curl.haxx.se')
   7 curl.setopt(pycurl.SHARE, s)
   8 curl.perform()
   9 curl.close()

Callbacks

为了更好的控制,libcurl允许把一些回调函数关联到每个连接中.在pycurl中,回调函数通过Curl对象调用setopt为s WRITEFUNCTION, READFUNCTION, HEADERFUNCTION, PROGRESSFUNCTION, IOCTLFUNCTION, 或DEBUGFUNCTION这些选项设置.这些选项对应着libcurl中CURLOPT_*前缀被移除的选项.在pycurl中回调函数必须是一个正规的Python函数,或者一个类的方法或是一个扩展的函数类型.

这儿有些局限性就是这些选项的回调函数有可能同时发生.它允许不同的回调函数对应到不同的Curl对象.更多明确的是,WRITEDATA的回调函数不能用于WRITEFUNCTION,READDATA的回调函数不能用于 READFUNCTION,WRITEHEADER的回调函数不能用于HEADERFUNCTION,PROGRESSDATA回调函数不能用于 PROGRESSFUNCTION,IOCTLDATA回调函数不能用于IOCTLFUNCTION,DEBUGDATA回调函数不能用于 DEBUGFUNCTION.实际上,可以通过把一个类的实例方法来当作回调函数并且使用类实例属性像文件对象那样存储每个对象的数据来克服这种局限性.

Pycurl中的每个回调函数的签名如下:

 

WRITEFUNCTION(string) -> number of characters written

READFUNCTION(number of characters to read)-> string

HEADERFUNCTION(string) -> number of characters written

PROGRESSFUNCTION(download total, downloaded, upload total, uploaded) -> status

DEBUGFUNCTION(debug message type, debug message string) -> None

IOCTLFUNCTION(ioctl cmd) -> status Example: Callbacks for document header and body

这个例子打印头数据到stderr打印内容数据到stdout.同样注意它们都不返回写入的字节数. WRITEFUNCTION和HEADERFUNCTION回调,写入所有字节时返回None.

切换行号显示
   1     ## Callback function invoked when body data is ready
   2     def body(buf):
   3         # Print body data to stdout
   4         import sys
   5         sys.stdout.write(buf)
   6         # Returning None implies that all bytes were written
   7 
   8     ## Callback function invoked when header data is ready
   9     def header(buf):
  10         # Print header data to stderr
  11         import sys
  12         sys.stderr.write(buf)
  13         # Returning None implies that all bytes were written
  14 
  15     c = pycurl.Curl()
  16     c.setopt(pycurl.URL, "http://www.python.org/")
  17     c.setopt(pycurl.WRITEFUNCTION, body)
  18     c.setopt(pycurl.HEADERFUNCTION, header)
  19     c.perform()

Example: Download/upload progress callback

这个例子演示如何使用进度回调.当下载一个文档时,uploads参数都将是0,反之亦然.

切换行号显示
   1     ## Callback function invoked when download/upload has progress
   2     def progress(download_t, download_d, upload_t, upload_d):
   3         print "Total to download", download_t
   4         print "Total downloaded", download_d
   5         print "Total to upload", upload_t
   6         print "Total uploaded", upload_d
   7 
   8     c.setopt(c.URL, "http://slashdot.org/")
   9     c.setopt(c.NOPROGRESS, 0)
  10     c.setopt(c.PROGRESSFUNCTION, progress)
  11     c.perform()

Example: Debug callbacks

这个例子演示如何使用调试回调.调试信息类型是一个调试信息的整数标示类型.在这个回调被调用时VERBOSE选项必须可用.

切换行号显示
   1     def test(debug_type, debug_msg):
   2         print "debug(%d): %s" % (debug_type, debug_msg)
   3 
   4     c = pycurl.Curl()
   5     c.setopt(pycurl.URL, "http://curl.haxx.se/")
   6     c.setopt(pycurl.VERBOSE, 1)
   7     c.setopt(pycurl.DEBUGFUNCTION, test)
   8     c.perform()

Other examples

Pycrul 也包含一些用于演示如何在libcurl中使用不同的回调的测试脚本和事例.例如,文件examples/file_upload.py包含如何使用 READFUNCTION的事例代码, 'tests/test_cb.py'演示WRITEFUNCTION和HEADERFUNCTION, 'tests/test_debug.py'演示DEBUGFUNCTION, 'tests/test_getinfo.py'演示PROGRESSFUNCTION. [全结束]

PS:本文翻译自PycURL的官方网站:http://pycurl.sourceforge.net/doc/pycurl.html,如有转贴请注明ChumpKlutz原创翻译

Trackback: http://tb.blog.youkuaiyun.com/TrackBack.aspx?PostId=2146192

 

2. PycURL for python26/win32

Compiled By andelf (andelf@gmail.com)

官方已经停在了 7.19.0 版本. 而且貌似很难编译.

这里提供 for python26 的 pycurl, 改了下版本号, 和 curl 相同, 为 10.4.22 最新软件包(所有).

  • OpenSSL 1.0.0
  • libcurl 7.20.1
  • zlib 1.2.5
  • c-ares 1.7.1
  • libssh2 1.2.5

静态编译版. 动态的 dll 太恐怖了.

 

pycurl.version
'libcurl/7.20.1 OpenSSL/1.0.0 zlib/1.2.5 c-ares/1.7.1 libssh2/1.2.5'

下载 zip: pycurl-7.20.1-bin-win32-py26.zip

exe 安装文件: pycurl-7.20.1.win32-py2.6.zip

 

From:http://wiki.woodpecker.org.cn/moin/PyCurl



转自:http://wiki.woodpecker.org.cn/moin/zspy

1. PycURL

Pycurl http://pycurl.sourceforge.net/

外部libcurl的接口,C写的,比urllib快,功能强.支持循环rewrite陷井的安全深度. 用于做网络爬虫,抓网页.

从 http://pycurl.sourceforge.net/download/ 下载 pycurl-ssl-7.16.4.win32-py2.5.exe 安装.

参考文献1,测试代码

切换行号显示
#像操作文件一样操作字符串,也可以from cStringIO import StringIO,性能应该会好一些
import StringIO

html = StringIO.StringIO()

import pycurl
c = pycurl.Curl()

c.setopt(pycurl.URL, 'http://www.baidu.com')

#写的回调
c.setopt(pycurl.WRITEFUNCTION, html.write)

c.setopt(pycurl.FOLLOWLOCATION, 1)

#最大重定向次数,可以预防重定向陷阱
c.setopt(pycurl.MAXREDIRS, 5)

#访问,阻塞到访问结束
c.perform()

#打印出 200(HTTP状态码) http://www.baidu.com(生效的url)
print c.getinfo(pycurl.HTTP_CODE), c.getinfo(pycurl.EFFECTIVE_URL)

#输出百度首页的html
#print html.getvalue()

然后看看多线程,http://pycurl.cvs.sourceforge.net/pycurl/pycurl/tests/ 有很多例子,还可做参考http://pycurl.sourceforge.net/doc/curlmultiobject.html

我自己改写了一个:)

切换行号显示
#!/usr/bin/env python
#coding=utf-8

import threading
import pycurl
from cStringIO import StringIO

class UrlOpen(threading.Thread):
    """异步下载网页"""

    def __init__(self):
        super(UrlOpen,self).__init__()
        self.opener = pycurl.CurlMulti()
        self.handle_list=[]

    def add(self,url,recall,writer=StringIO()):
        """
        参数:网址,回调函数,存放临时数据的对象
        """
        c = pycurl.Curl()

        #可以传给回调函数
        c.url=url
        c.content = writer
        c.recall = recall
        c.setopt(c.URL,url)
        c.setopt(c.WRITEFUNCTION,c.content.write)

        self.handle_list.append(c)
        self.opener.add_handle(c)

    def _remove(self,c):
        c.close()
        self.opener.remove_handle(c)
        self.handle_list.remove(c)


    def run(self):
        num_handle=len(self.handle_list)
        while 1:
            ret = self.opener.select(10.0)
            if ret == -1:  continue
            while 1:
                num_handle_pre=num_handle
                ret, num_handle =self.opener.perform()
                #活动的连接数改变时
                if num_handle!=num_handle_pre:
                    result=self.opener.info_read()
                    print result
                    for i in result[1]:
                        #成功
                        i.http_code = i.getinfo(i.HTTP_CODE)
                        self._remove(i)
                        i.recall(i)
                    for i in result[2]:
                        #失败,应该记录一下
                        self._remove(i)

                if ret != pycurl.E_CALL_MULTI_PERFORM:
                    break

_opener=None
def urlopen(*arg,**key):
    global _opener
    if _opener is None:
        _opener=UrlOpen()
        _opener.add(*arg,**key)
        _opener.start()
    else:
        _opener.add(*arg,**key)

def show(x):
    print x.content.getvalue()
if __name__=="__main__":
    urlopen("http://www.baidu.com/",show)
    _opener.join()

又封装了一个异步打开网页的类和函数

#coding=utf-8

import threading
from cStringIO import StringIO
import pycurl
"""
Asyn open url
Author:zsp007@gmail.com
2008-1-25 17:14
"""
from Queue import Queue,Empty

class UrlOpen(threading.Thread):
   """异步下载网页"""

   def __init__(self):
       super(UrlOpen, self).__init__()
       self.opener = pycurl.CurlMulti()
       self.handle_list = []
       self.waiting = Queue(2048)

   def add(self, url, recall, catch=None, writer=StringIO):
       """
       参数:网址,回调函数,存放临时数据的对象
       """
       if catch is None:
           def catch(curl, error_no, desp):
               print "Url:%s\nError:%s - %s"%(curl.url, error_no, desp)

       c = pycurl.Curl()

       #可以传给回调函数
       c.url = url
       c.content = writer()
       c.recall = recall
       c.catch = catch
       c.setopt(c.URL,
           url.encode('utf-8') if type(url) is unicode else url
       )
       c.setopt(c.WRITEFUNCTION, c.content.write)
       c.setopt(pycurl.CONNECTTIMEOUT, 30)
       c.setopt(pycurl.MAXREDIRS, 3)
       c.setopt(pycurl.TIMEOUT, 300)
       c.setopt(pycurl.FOLLOWLOCATION, 1)

       self.waiting.put(c)

   def _add(self,c):
       self.handle_list.append(c)
       self.opener.add_handle(c)

   def _pull(self):
       while True:
           try:
               self._add(self.waiting.get_nowait())
           except Empty:
               break

   def _remove(self, c):
       c.close()
       self.opener.remove_handle(c)
       self.handle_list.remove(c)
       del c

   def run(self):
       import select
       import time
       num_handle = 0
       while 1:
           #print 1
           if self.handle_list:
               #print "select start"
               ret = self.opener.select(1.0)
               #print "select end"
               if ret >= 0:
                   while 1:
                       #print "perform start"
                       num_handle_pre = num_handle
                       ret, num_handle = self.opener.perform()
                       #print "preform end"
                       #活动的连接数改变时
                       if num_handle != num_handle_pre:
                           result = self.opener.info_read()
                           for i in result[1]:
                               #成功
                               i.http_code = i.getinfo(i.HTTP_CODE)
                               i.recall(i)
                               self._remove(i)
                           for i in result[2]:
                               #失败,应该记录一下,或回调失败函数
                               #i为(<pycurl.Curl object at
0x00C04C80>, 6, 'Could not resolve host: www.msn.com (Domain name not
found)')
                               i[0].catch(*i)
                               self._remove(i[0])
                       if ret != pycurl.E_CALL_MULTI_PERFORM:
                           #print "break"
                           break
                       self._pull()
               self._pull()
           else:
               self._add(self.waiting.get())

_opener = None
def urlopen(*arg, **key):
   global _opener
   if _opener is None:
       _opener = UrlOpen()
       _opener.start()
   _opener.add(*arg, **key)
import time
if __name__ == "__main__":
   link = ['http://www.baidu.com/', 'http://www.sina.com.cn',
'http://www.qq.com', 'http://www.sohu.com', 'http://www.163.com/',
'http://www.ifeng.com/', 'http://www.cctv.com/default.shtml',
'http://www.xinhuanet.com/', 'http://www.people.com.cn/',
'http://cn.msn.com/', 'http://www.google.cn/', 'http://cn.yahoo.com/',
'http://www.amazon.cn/?source=2009hao123famousdaohang',
'http://www.chinamobile.com/', 'http://www.pconline.com.cn/',
'http://www.chinahr.com/', 'http://www.gov.cn/',
'http://www.zhcw.com/', 'http://www.autohome.com.cn/',
'http://www.zhaopin.com/Market/hao123.jsp',
'http://fund.eastmoney.com/', 'http://www.eastmoney.com/',
'http://www.xiaonei.com/', 'http://www.soufun.com/',
'http://www.51.com/', 'http://www.rayli.com.cn/',
'http://youa.baidu.com/', 'http://www.360.cn/',
'http://www.ctrip.com/', 'http://www.xcar.com.cn/',
'http://www.qq163.com', 'http://www.samsung.com/',
'http://www.zol.com.cn/', 'http://www.taobao.com/',
'http://www.icbc.com.cn/', 'http://www.sto.cn',
'http://www.dianping.com', 'http://www.gougou.com',
'http://www.ct10000.com', 'http://www.anjuke.com/?&amp;pi=H-1',
'http://www.360buy.com/union/union_default.asp?union_Id=75',
'http://tl.sohu.com/?rcc_id=061f93406c7a77d6a6e4c8647b09fb56',
'http://www.51job.com/default.php?code=gb2312',
'http://central.dangdang.com/league/leagueref.asp?from=P-227107a&amp;backurl=http://a.oadz.com/link/C/51/52648/ZzZIg.TXwwIV69FJbh3yJe4H7WI_/a/898?home.dangdang.com',
'http://www.jiayuan.com/st/?id=3237&amp;url=http://www.jiayuan.com']
   link +=['http://www.qidian.com/', 'http://www.readnovel.com/',
'http://www.hongxiu.com/', 'http://www.bookge.com/',
'http://www.jjwxc.net/', 'http://hjsm.tom.com/',
'http://www.4yt.net/', 'http://www.cuiweiju.com/',
'http://book.sina.com.cn/', 'http://www.xxsy.net/',
'http://www.wansong.net/', 'http://www.myfreshnet.com/',
'http://www.fmx.cn/', 'http://www.xs8.cn/',
'http://www.rongshuxia.com/', 'http://www.booksky.org/',
'http://www.zhulang.com/', 'http://www.3320.net/',
'http://www.17k.com/', 'http://www.xhsd.net/',
'http://www.qukanshu.com/', 'http://www.fbook.net/',
'http://www.duyidu.com/', 'http://www.soso999.com/',
'http://www.junzitang.com/', 'http://msn.hongxiu.com/',
'http://www.yuanwen.com/', 'http://top.baidu.com/book.html',
'http://www.lcread.com/', 'http://www.sodu.com.cn/',
'http://www.cc222.com/', 'http://www.feiku.com/',
'http://book.hqdoor.com/', 'http://book.sooyuu.com/',
'http://www.52eshu.com/', 'http://bbs.91txt.com/',
'http://book.qq.com/', 'http://book.sohu.com/',
'http://www.baidu.com/search/guoxue/dir/fenlei.html',
'http://wind.yinsha.com/', 'http://www.duzhe.com/',
'http://www.storychina.cn/', 'http://www.shigeku.org/',
'http://www.goodmood.cn/', 'http://www.nlc.gov.cn/',
'http://www.qnwz.cn/', 'http://wenxue.xilu.com/']
   link +=['http://www.ganji.com/', 'http://www.58.com/',
'http://www.baixing.com/', 'http://www.263.com/',
'http://www.kuxun.cn/', 'http://www.mangocity.com/',
'http://www.qunar.com/', 'http://www.dianping.com/',
'http://www.fantong.com/', 'http://www.55bbs.com/',
'http://www.19lou.com/', 'http://www.koubei.com/',
'http://www.nike.com.cn/', 'http://www.li-ning.com.cn/',
'http://www.bosideng.com/', 'http://www.pirateship.com.cn/',
'http://www.goelia.com.cn/', 'http://www.adidas.com/',
'http://www.converse.com.cn/', 'http://www.romon.com/index.php',
'http://www.youngor.com/', 'http://www.etam.com.cn',
'http://www.heilanhome.com/', 'http://www.mizuno.com.cn/',
'http://www.goldlion-china.com/', 'http://www.phland.com.cn/',
'http://www.betu.com.hk/', 'http://www.puma.com.cn/',
'http://www.anta.com/', 'http://www.pierrecardin.com.cn/',
'http://www.bobdog.com.cn/', 'http://www.idaphne.com/',
'http://www.e-giordano.com/', 'http://www.361sport.com/',
'http://www.levi.com.cn/', 'http://www.lee.com.cn/',
'http://www.shanshan.com/', 'http://www.semir.com',
'http://www.versace.com/flash.html', 'http://www.k-boxing.com/',
'http://only.nzn.cn/', 'http://www.pb89.com/%20',
'http://www.aimer.com.cn/', 'http://www.balenciaga.com',
'http://www.ordifen.com.cn/', 'http://www.ochirly.com/',
'http://www.uggaustralia.com/', 'http://www.jshyx.com/',
'http://www.givenchy.com/default.php',
'http://www.thenorthface.com.cn/', 'http://www.tissot.com.hk/',
'http://www.azona.com.hk/', 'http://www.3suisses.com.cn/',
'http://www.valentino.it/', 'http://www.yishion.com.cn/',
'http://www.chowtaiseng.com/', 'http://www.tsljewellery.com/',
'http://www.jeanswest.com/', 'http://www.baoxiniao.com.cn/',
'http://www.qsyr.com/%20', 'http://www.septwolves.com/',
'http://www.baleno.com.hk/', 'http://www.belle.com.cn/',
'http://www.teenmix.com.cn/', 'http://www.fairwhale.com.cn/',
'http://www.swatch.com.cn/', 'http://www.staccato.com/',
'http://www.daphne.com.cn/', 'http://www.c-banner.com/',
'http://www.xtep.com.cn/', 'http://www1.jeanswest.com.cn/',
'http://www.kappa.com.cn/', 'http://www.laofengxiang.com/',
'http://www.cnhqt.com/', 'http://www.tatashoes.com.cn/',
'http://www.robinhood.com.cn/', 'http://www.doublestar.com.cn/',
'http://www.ozarkgear.com.cn/', 'http://www.aokang.com.cn/',
'http://www.ctf.com.cn/', 'http://www.crpttan.com/',
'http://www.calvinklein.com/', 'http://www.citizen.com.cn/',
'http://www.longines.com/', 'http://www.jackjonescn.net/',
'http://www.famoustone.com/', 'http://www.kfc.com.cn/',
'http://www.bjyoshinoya.com.cn/', 'http://www.starbucks.cn/',
'http://www.icoke.cn/', 'http://www.mengniu.com.cn/',
'http://www.mcdonalds.com.cn/', 'http://www.yonghe.com.cn/',
'http://www.ubccn.com/', 'http://www.dicos.com.cn/',
'http://www.yili.com/', 'http://www.pizzahut.com.cn/',
'http://www.quanjude.com.cn/direct.php', 'http://www.nescafe.com.cn/',
'http://www.masterkong.com.cn/', 'http://www.heinz.com.cn/',
'http://www.origus.com/', 'http://www.xfy.com.cn/',
'http://www.haagendazs.com.cn/', 'http://www.wyeth.com.cn/',
'http://www.moutaichina.com/index.asp', 'http://www.tsingtao.com.cn/',
'http://www.meadjohnson.com.cn/', 'http://www.dumex.com.cn/',
'http://www.wuliangye.com.cn/', 'http://www.zkungfu.com/',
'http://www.dovechocolate.com.cn/',
'http://www.ganso.com.cn/%20%20%20', 'http://www.beingmate.com/',
'http://www.waffleboy.com.cn/', 'http://www.holiland.com.cn/',
'http://www.goldenjaguar.com/', 'http://www.huiyuan.com.cn/%20%20%20',
'http://www.hsufuchifoods.com/%20%20%20%20',
'http://www.maybellinechina.com/', 'http://www.dabao.com/',
'http://www.lorealchina.com/', 'http://www.shiseidochina.com/',
'http://www.esteelauder.com.cn/',
'http://www.avon.com.cn/PRSuite/home/home.jsp',
'http://www.tjoy.biz/',
'http://www.lancome.com.cn/_zh/_cn/index.aspx',
'http://www.kose.co.jp/', 'http://www.h2oplus.com.hk/',
'http://www.yuesai.com.cn/', 'http://www.nivea.com.cn/',
'http://www.chanel.com/',
'http://www.clinique.com.cn/index.tmpl?ngextredir=1',
'http://www.ponds.com.cn/', 'http://www.vichy.com.cn/',
'http://www.efu.org.cn/',
'http://www.laneigechina.com/Front-Page/index2.jsp',
'http://www.olay.com.cn/', 'http://www.guerlain.com.cn/',
'http://www.aupres-shiseido.com.cn/',
'http://www.dior.com/pcd/International/JSP/Home/prehomeFlash.jsp',
'http://www.herborist.com.cn/', 'http://www.dhc.net.cn/',
'http://www.ysl.com/', 'http://www.kose.com.cn/',
'http://www.liangfei.com/', 'http://www.tayoi.com/',
'http://www.chcedo.com/', 'http://www.head-shoulders.com.cn/',
'http://www.slek.com.cn/', 'http://www.mentholatum.com.cn/',
'http://www.pg.com.cn/', 'http://www.china-ajjj.com/',
'http://www.rejoice.com.cn/', 'http://www.cnnice.com/',
'http://www.watsons.com.cn/', 'http://www.unilever.com.cn/',
'http://www.ikea.com/cn/zh/', 'http://www.pantene.com.cn/',
'http://www.colgate.com.cn/app/Colgate/CN/HomePage.cvsp',
'http://www.auchan.com.cn/', 'http://www.c-bons.com.cn/',
'http://www.carrefour.com.cn/', 'http://www.vs.com.cn/',
'http://www.crest.com.cn/', 'http://www.tongrentang.com/',
'http://www.amway.com.cn/index.aspx', 'http://www.wal-martchina.com/',
'http://www.tupperware.com.cn/', 'http://www.ourlotus.com/',
'http://www.skyworth.com/cn/', 'http://www.sony.com.cn/',
'http://www.siemens.com.cn/', 'http://www.gree.com.cn/',
'http://www.shinco.com/', 'http://www.midea.com.cn/',
'http://www.samsung.com.cn/', 'http://www.hitachi-shha.com.cn/',
'http://www.electrolux.com.cn/', 'http://www.toshiba.com.cn/',
'http://www.panasonic.com.cn/', 'http://www.canon.com.cn/',
'http://www.tcl.com/', 'http://www.lg.com.cn/',
'http://cn.changhong.com/', 'http://www.haier.com/',
'http://www.philips.com.cn/', 'http://www.konka.com/',
'http://www.rsd.com.cn/', 'http://www.supor.com.cn/',
'http://www.fotile.com/', 'http://www.cnsuning.com/',
'http://www.sharp.cn/', 'http://www.galanz.com.cn/',
'http://www.chinamacro.cn/', 'http://www.robam.com/',
'http://www.gome.com.cn/', 'http://www.joyoung.com.cn/',
'http://www.staccato.com/', 'http://www.meiling.com/',
'http://www.fushibao.com/', 'http://www.sacon.cn/',
'http://www.yongle.com.cn/', 'http://www.xinfei.com/']

   begin = time.time()
   number = 0
   dumped = set()
   def show(c):
       global number
       number +=1

       content = c.content.getvalue()
       print number,". cost time", time.time() - begin,"htmllen", len(content)
       print c.url
       begin_pos = None
       count = 1
       while True:
           pos = content.rfind('<a href="http://',None,begin_pos)
           #print content[pos:pos+200]
           if pos!=-1:
               begin_pos = pos
               url = content[pos+9:content.find('"',pos+13)]
               if url in dumped:
                   return
               dumped.add(url)
               print "\tadd",url
               urlopen(url,show)
               count +=1
               if count>10:
                   break
           else:
               break
   link = set(link)
   print "total link", len(link)
   for i in link:
       urlopen(i, show)
       dumped.add(i)
   _opener.join()
   print "cost time", time.time() - begin

1.1. 相关文献


转自:http://wiki.woodpecker.org.cn/moin/PyCurl

1. PycURL

pycurl — A Python interface to the cURL library

Pycurl包是一个libcurl的Python接口.pycurl已经成功的在Python2.2到Python2.5版编译测试过了.

Libcurl 是一个支持FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE 和 LDAP的客户端URL传输库.libcurl也支持HTTPS认证,HTTP POST,HTTP PUT,FTP上传,代理,Cookies,基本身份验证,FTP文件断点继传,HTTP代理通道等等.

Libcurl提供的所有功能都可以通过pycurl接口来使用.接下来的子章节概述怎么使用pycurl接口,并且假定已经知道了libcurl如何工作的.libcurl如何工作的更多信息,请参考curl库的web页面(http://curl.haxx.se/libcurl/c/). Module Functionality

pycurl.global_init(option) ->None 选项是以下常量之一:pycurl.GLOBAL_SSL, pycurl.GLOBAL_WIN32, pycurl.GLOBAL_ALL, pycurl.GLOBAL_NOTHING, pycurl.GLOBAL_DEFAULT. 相应的是libcurl的 curl_global_init() 方法.

pycurl.global_cleanup() -> None 相应的是libcurl的curl_global_cleanup()方法.

pycurl.version 这是liburl当前版本的信息,相应的是liburl的curl_version()方法. 用法举例:

切换行号显示
>>> import pycurl
>>> pycurl.version
'libcurl/7.12.3 OpenSSL/0.9.7e zlib/1.2.2.1 libidn/0.5.12'

pycurl.version_info() -> Tuple

相对应的是libcurl中的 curl_version_info() 方法. 返回一个序列信息就像liburl的curl_version_info()方法返回的 curl_version_info_data 结构化数据.

用法举例:

切换行号显示
>>> import pycurl
>>> pycurl.version_info()
(2, '7.12.3', 461827, 'i586-pc-linux-gnu', 1565, 'OpenSSL/0.9.7e', 9465951,
'1.2.2.1', ('ftp', 'gopher', 'telnet', 'dict', 'ldap', 'http', 'file',
'https', 'ftps'), None, 0, '0.5.12')

pycurl.Curl() -> Curl object

这个函数创建一个同libcurl中的CURL处理器相对应的Curl对象.Curl对象自动的设置CURLOPT_VERBOSE为0, CURLOPT_NOPROGRESS为1,提供一个默认的CURLOPT_USERAGENT和设置CURLOPT_ERRORBUFFER指向一个私有的错误缓冲区.

pycurl.CurlMulti() -> CurlMulti object

这个函数创建一个新的与libcurl中的CURLM处理器相对应的CurlMulti对象.

pycurl.CurlShare() -> CurlShare object

这个函数创建一个新的与libcurl中的CURLSH处理器相对应的CurlShare对象.CurlShare对象可以在Curl对象上传递SHARE选项参数. [待续]

Trackback: http://tb.blog.youkuaiyun.com/TrackBack.aspx?PostId=2146079

Subsections # Curl objects CurlMulti objects CurlShare objects # Callbacks Curl Object

Curl对象具有以下方法:

close() -> None 对应的是libcurl中的curl_easy_cleanup方法.当Curl对象不再被引用时pycurl会自动调用这个方法,但也可直接地调用这个方法.

perform() -> None 对应于libcurl中的curl_easy_perform方法.

setopt(option, value) -> None 对应于libcurl中的curl_easy_setopt方法, option使用libcurl中的CURLOPT_*常量来指定,只可惜CURLOPT_前缀现在已经被去掉了.value的数据类型依赖于 option,它可以是一个字符串,整型,长整型,文件对象,列表或是函数.

用法举例:

切换行号显示
import pycurl
c = pycurl.Curl()
c.setopt(pycurl.URL, "http://www.python.org/")
c.setopt(pycurl.HTTPHEADER, ["Accept:"])
import StringIO
b = 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方法, option同样使用libcurl中的CURLOPT_*常量来指定,只可惜CURLOPT_前缀现在已经被去掉了. Result包含一个整数,浮点数或字符串,这都信赖于给定的option.getinfo方法不能在perform方法未调用或完成之前进行调用.

用法举例:

errstr() -> String 返回这个处理器中内部libcurl错误缓冲区的字符串表示. CurlMulti Object

CurlMulti对象具有以下方法:

close() -> None 对应于libcurl中的curl_multi_cleanup()方法.当CurlMulti对象不再被引用时pycurl会自动调用该方法,也可显示调用该方法.

perform() -> tuple of status and the number of active Curl objects 对应于libcurl中的curl_multi_perform()方法.

add_handle(Curl object) -> None 对应于libcurl中的curl_multi_add_handle()方法.这个方法添加一个有效的Curl对象到CurlMulti对象. 重要提示:add_handle没有隐式的增加对Curl对象的引用(因而也没有增加Curl对象的引用次数)

remove_handle(Curl object) -> None 对应于libcurl中的curl_multi_remove_handle()方法.这个方法从CurlMulti对象中移除一个现有的Curl对象. 重要提示:remove_handle不会隐式的移除Curl对象的引用(因而不会减少Curl对象的引用次数).

fdset() -> triple of lists with active file descriptors, readable, writeable, exceptions. 对应于libcurl中的curl_multi_fdset()方法.这个方法从CurlMulti对象中提取文件描述信息.返回的列表可以被用于select模块to poll for events.

用法举例:

切换行号显示
import pycurl
c = pycurl.Curl()
c.setopt(pycurl.URL, "http://curl.haxx.se")
m = pycurl.CurlMulti()
m.add_handle(c)
while 1:
    ret, num_handles = m.perform()
    if ret != pycurl.E_CALL_MULTI_PERFORM: break
while num_handles:
    apply(select.select, m.fdset() + (1,))
    while 1:
        ret, num_handles = m.perform()
        if ret != pycurl.E_CALL_MULTI_PERFORM: break

select(timeout) -> number of ready file descriptors or -1 on timeout 这是一个有用的函数,它简化了fdest()和select模块的组合使用.

用法举例:

切换行号显示
import pycurl
c = pycurl.Curl()
c.setopt(pycurl.URL, "http://curl.haxx.se")
m = pycurl.CurlMulti()
m.add_handle(c)
while 1:
    ret, num_handles = m.perform()
    if ret != pycurl.E_CALL_MULTI_PERFORM: break
while num_handles:
    ret = m.select(1.0)
    if ret == -1:  continue
    while 1:
        ret, num_handles = m.perform()
        if ret != pycurl.E_CALL_MULTI_PERFORM: break

info_read([max]) -> numberof queued messages, a list of successful objects, a list of failed objects 对应于libcurl中的curl_multi_info_read()方法.这个方法从多重栈中提取至多max个信息然后返回两个列表.第一个列表包含成功完成的操作第二个列表包含每一个失败的curl对象的<curl对象,curl错误代码,curl错误信息>序列. [待续]

PS:本文翻译自PycURL的官方网站:http://pycurl.sourceforge.net/doc/pycurl.html,如有转贴请注明ChumpKlutz原创翻译

Trackback: http://tb.blog.youkuaiyun.com/TrackBack.aspx?PostId=2146140

CurlShare Object

CurlShare对象具有以下方法:

setopt(option, value) -> None 对应于libcurl中的curl_share_setopt方法, option使用libcurl中的CURLOPT_*常量来指定,只可惜CURLOPT_前缀现在改成SH_了.通常value必须是 LOCK_DATA_COOKIE 或者说LOCK_DATA_DNS.

用法举例:

切换行号显示
import pycurl
curl = pycurl.Curl()
s = pycurl.CurlShare()
s.setopt(pycurl.SH_SHARE, pycurl.LOCK_DATA_COOKIE)
s.setopt(pycurl.SH_SHARE, pycurl.LOCK_DATA_DNS)
curl.setopt(pycurl.URL, 'http://curl.haxx.se')
curl.setopt(pycurl.SHARE, s)
curl.perform()
curl.close()

Callbacks

为了更好的控制,libcurl允许把一些回调函数关联到每个连接中.在pycurl中,回调函数通过Curl对象调用setopt为s WRITEFUNCTION, READFUNCTION, HEADERFUNCTION, PROGRESSFUNCTION, IOCTLFUNCTION, 或DEBUGFUNCTION这些选项设置.这些选项对应着libcurl中CURLOPT_*前缀被移除的选项.在pycurl中回调函数必须是一个正规的Python函数,或者一个类的方法或是一个扩展的函数类型.

这儿有些局限性就是这些选项的回调函数有可能同时发生.它允许不同的回调函数对应到不同的Curl对象.更多明确的是,WRITEDATA的回调函数不能用于WRITEFUNCTION,READDATA的回调函数不能用于 READFUNCTION,WRITEHEADER的回调函数不能用于HEADERFUNCTION,PROGRESSDATA回调函数不能用于 PROGRESSFUNCTION,IOCTLDATA回调函数不能用于IOCTLFUNCTION,DEBUGDATA回调函数不能用于 DEBUGFUNCTION.实际上,可以通过把一个类的实例方法来当作回调函数并且使用类实例属性像文件对象那样存储每个对象的数据来克服这种局限性.

Pycurl中的每个回调函数的签名如下:

WRITEFUNCTION(string) -> number of characters written

READFUNCTION(number of characters to read)-> string

HEADERFUNCTION(string) -> number of characters written

PROGRESSFUNCTION(download total, downloaded, upload total, uploaded) -> status

DEBUGFUNCTION(debug message type, debug message string) -> None

IOCTLFUNCTION(ioctl cmd) -> status Example: Callbacks for document header and body

这个例子打印头数据到stderr打印内容数据到stdout.同样注意它们都不返回写入的字节数. WRITEFUNCTION和HEADERFUNCTION回调,写入所有字节时返回None.

切换行号显示
    ## Callback function invoked when body data is ready
    def body(buf):
        # Print body data to stdout
        import sys
        sys.stdout.write(buf)
        # Returning None implies that all bytes were written

    ## Callback function invoked when header data is ready
    def header(buf):
        # Print header data to stderr
        import sys
        sys.stderr.write(buf)
        # Returning None implies that all bytes were written

    c = pycurl.Curl()
    c.setopt(pycurl.URL, "http://www.python.org/")
    c.setopt(pycurl.WRITEFUNCTION, body)
    c.setopt(pycurl.HEADERFUNCTION, header)
    c.perform()

Example: Download/upload progress callback

这个例子演示如何使用进度回调.当下载一个文档时,uploads参数都将是0,反之亦然.

切换行号显示
    ## Callback function invoked when download/upload has progress
    def progress(download_t, download_d, upload_t, upload_d):
        print "Total to download", download_t
        print "Total downloaded", download_d
        print "Total to upload", upload_t
        print "Total uploaded", upload_d

    c.setopt(c.URL, "http://slashdot.org/")
    c.setopt(c.NOPROGRESS, 0)
    c.setopt(c.PROGRESSFUNCTION, progress)
    c.perform()

Example: Debug callbacks

这个例子演示如何使用调试回调.调试信息类型是一个调试信息的整数标示类型.在这个回调被调用时VERBOSE选项必须可用.

切换行号显示
    def test(debug_type, debug_msg):
        print "debug(%d): %s" % (debug_type, debug_msg)

    c = pycurl.Curl()
    c.setopt(pycurl.URL, "http://curl.haxx.se/")
    c.setopt(pycurl.VERBOSE, 1)
    c.setopt(pycurl.DEBUGFUNCTION, test)
    c.perform()

Other examples

Pycrul 也包含一些用于演示如何在libcurl中使用不同的回调的测试脚本和事例.例如,文件examples/file_upload.py包含如何使用 READFUNCTION的事例代码, 'tests/test_cb.py'演示WRITEFUNCTION和HEADERFUNCTION, 'tests/test_debug.py'演示DEBUGFUNCTION, 'tests/test_getinfo.py'演示PROGRESSFUNCTION. [全结束]

PS:本文翻译自PycURL的官方网站:http://pycurl.sourceforge.net/doc/pycurl.html,如有转贴请注明ChumpKlutz原创翻译

Trackback: http://tb.blog.youkuaiyun.com/TrackBack.aspx?PostId=2146192

2. PycURL for python26/win32

Compiled By andelf (andelf@gmail.com)

官方已经停在了 7.19.0 版本. 而且貌似很难编译.

这里提供 for python26 的 pycurl, 改了下版本号, 和 curl 相同, 为 10.4.22 最新软件包(所有).

  • OpenSSL 1.0.0
  • libcurl 7.20.1
  • zlib 1.2.5
  • c-ares 1.7.1
  • libssh2 1.2.5

静态编译版. 动态的 dll 太恐怖了.

pycurl.version
'libcurl/7.20.1 OpenSSL/1.0.0 zlib/1.2.5 c-ares/1.7.1 libssh2/1.2.5'

下载 zip: pycurl-7.20.1-bin-win32-py26.zip

exe 安装文件: pycurl-7.20.1.win32-py2.6.zip

3. 下载

for win32, win64 http://www.lfd.uci.edu/~gohlke/pythonlibs/



1、使用getinfo来获得更多的信息:
#! /usr/bin/env python
# vi:ts=4:et
# $Id: test_getinfo.py,v 1.18 2003/05/01 19:35:01 mfx Exp $
# Author BY MSN:pt007@vip.sina.com
import time
import pycurl


## Callback function invoked when progress information is updated
#下面的函数用来显示下载的进度:
def progress(download_t, download_d, upload_t, upload_d):
   print "Total to download %d bytes, have %d bytes so far" % \
       (download_t, download_d)

url = "http://www.sohu.com/index.html"

print "Starting downloading", url
print
f = open("body.html", "wb") #新建一个文件并返回文件描述字,f用来保存返回的网页内容
h = open("header.txt", "wb")#h用来保存返回的包头header信息
i = open("info.txt","wb") #i用来保存getinfo()函数取回的信息
c = pycurl.Curl()
c.setopt(c.URL, url) #设置要访问的网址
c.setopt(c.WRITEDATA, f) #将返回的网页内容写入f文件描述字
c.setopt(c.NOPROGRESS, 0)
c.setopt(c.PROGRESSFUNCTION, progress)#调用过程函数
c.setopt(c.FOLLOWLOCATION, 1)
c.setopt(c.MAXREDIRS, 5)
c.setopt(c.WRITEHEADER, h)#将返回的包头header内容写入h文件描述字
c.setopt(c.OPT_FILETIME, 1)
c.perform() #执行上述访问网址的操作

print
print "HTTP-code:", c.getinfo(c.HTTP_CODE) #Outputs:200
buf=c.getinfo(c.HTTP_CODE)
i.write("HTTP-code:"+str(buf)) #将输出写入到i文件描述字中
print "Total-time:", c.getinfo(c.TOTAL_TIME) #下载总时间:0.795
buf=c.getinfo(c.TOTAL_TIME)
i.write(&#39;\r\n&#39;)
i.write("Total-time:"+str(buf))
print "Download speed: %.2f bytes/second" % c.getinfo(c.SPEED_DOWNLOAD) #下载速度:261032.00 bytes/second
print "Document size: %d bytes" % c.getinfo(c.SIZE_DOWNLOAD) #下载文档的大小:207521 bytes
print "Effective URL:", c.getinfo(c.EFFECTIVE_URL) #有效网址:http://www.sohu.com/index.html
print "Content-type:", c.getinfo(c.CONTENT_TYPE) #text/html
print "Namelookup-time:", c.getinfo(c.NAMELOOKUP_TIME) #DNS解析速度:0.065
print "Redirect-time:", c.getinfo(c.REDIRECT_TIME) #0.0
print "Redirect-count:", c.getinfo(c.REDIRECT_COUNT) #0
epoch = c.getinfo(c.INFO_FILETIME)
print "Filetime: %d (%s)" % (epoch, time.ctime(epoch)) #文件下载时间:1172361818 (Sun Feb 25 08:03:38 2007)
print
print "Header is in file &#39;header.txt&#39;, body is in file &#39;body.html&#39;"

c.close()
f.close()
h.close()


2、简单用法:
#!c:\python25\python
# vi:ts=4:et
# $Id: test_cb.py,v 1.14 2003/04/21 18:46:10 mfx Exp $
# Author BY MSN:pt007@vip.sina.com

import sys
import pycurl

## Callback function invoked when body data is ready
def body(buf):
   # Print body data to stdout
   sys.stdout.write(buf) #将buf的内容输出到标准输出
   

## Callback function invoked when header data is ready
def header(buf):
   # Print header data to stderr
   sys.stdout.write(buf)

c = pycurl.Curl()
c.setopt(pycurl.URL, &#39;http://www.sohu.com/&#39;) #设置要访问的网址
c.setopt(pycurl.WRITEFUNCTION, body) #调用body()函数来输出返回的信息
c.setopt(pycurl.HEADERFUNCTION, header)#调用header()函数来输出返回的信息
c.setopt(pycurl.FOLLOWLOCATION, 1)
c.setopt(pycurl.MAXREDIRS, 5)
c.perform() #执行上述访问网址的操作
c.close()


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值