免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 8567 | 回复: 7
打印 上一主题 下一主题

写了一个简单的下载程序(23/07/2006更新) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-07-21 21:18 |只看该作者 |倒序浏览
#这是一个简单的单线程下载程序,下载的是我网站里的一个小游戏,挖金子。PYTHON刚刚接触,书刚看到函数那里,看不下去了,太枯燥了,就试着自己做一个小玩意提提兴趣。
#其中肯定有很多问题,比如说比较笨的处理方法,请大家给我指出。


  1. # _*_ coding:cp936 _*_
  2. #Sample downloads Program use httplib
  3. #Programer:rikioy
  4. #email:rikiy at gmail.com
  5. #date:2006-07-21
  6. #introduction:
  7. #这是一个简单的单线程下载程序,下载的是我网站里的一个小游戏,挖金子。PYTHON刚刚接触,书刚看到函数那里,看不下去了,太枯燥了,就试着自己做一个小玩意提提兴趣。
  8. #其中肯定有很多问题,比如说比较笨的处理方法,请大家给我指出。
  9. #用到的知识主要有:
  10. #1、httplib库的使用,会用就简单多啦。
  11. #2、设置引用页,有些网站下载需要,类似FLASHGET中的设置引用页。其实也是httplib中的知识。
  12. #3、下载进度的计算,这个难道我一个下午,没经验的结果。虽然现在设计的也不好,不能用于多线程,不过以后在改吧。
  13. #4、输出百分比,这个也小难了一会,不过后来找到方法了。用退格。呵呵。
  14. #遗憾:
  15. #1、rMsg是要下载文件的总大小,在计算进度的时候 percent = round(totle/fsize*100) 中 fsize 直接用 rMsg是不行的,弄了一下午才找到是这个问题,为什么,还不知道。
  16. #2、文件变量用的比较乱,太晚了,不想整理了。
  17. #3、没有任何异常处理,太脆弱了。
  18. #改进:
  19. #1、改成多进程的。
  20. #2、下载任务考文本文件来配置
  21. #3、整理程序中的变量与结构,使之更合理。
  22. #4、加入异常处理
  23. #感谢:
  24. #BAIDU,我在百度搜索到了很多有用的东西。
  25. #GOODNAME008,看了他写的一个简单的关于下载文件的文章,并且不厌其烦地回答我弱智的问题。BLOG,http://blog.csdn.net/goodname008
  26. #
  27. #


  28. #引入HTTPLIB的库,URLLIB2也可以做个事情,但PY文档里面HTTPLIB介绍的比较多,所以就用这个了
  29. import httplib
  30. #单线程
  31. import threading
  32. #在最后计算下载百分比的时候用到了时间库
  33. import time

  34. class download(threading.Thread):
  35.     def __init__ (self,threadname):
  36.         threading.Thread.__init__(self,name=threadname)
  37.     def run(self):
  38.         #设置HTTP连接实例
  39.         conn = httplib.HTTPConnection("www.wowor.org")
  40.         #发送GET请求,在httplib中有putrequest和request两种,在MANUALS中有,不能混用。
  41.         conn.putrequest('GET','/wjz.exe')
  42.         #PUT头,Referer也是设置引用页的地方。
  43.         conn.putheader('Referer','http://bbs.pingshu8.com')
  44.         #PUT header结束,不结束后面进行不了。
  45.         conn.endheaders()
  46.         #得到服务器回应
  47.         rMsg = conn.getresponse()
  48.         #建立文件 fwrite
  49.         fwrite = open('wjz.exe','wb+')
  50.         #total后面计算进度用的,已下载量。
  51.         totle = 0.00
  52.         #全局变量 percent = 百分比
  53.         global percent
  54.         #取得服务器返回的文件大小,length 文档中好像没有,我在LIB代码中查到的。
  55.         fsize = rMsg.length
  56.         #输出最后加逗号,不换行。
  57.         print "Thread download start...",
  58.         #每次读取一千字节放到 ftmp 中
  59.         ftmp = rMsg.read(1000)
  60.         #开始循环读,并且 用percent = round(totle/fsize*100)计算百分比
  61.         while len(ftmp):
  62.             fwrite.write(ftmp)
  63.             totle = totle + len(ftmp)
  64.             percent = totle/fsize*100
  65.             ftmp = rMsg.read(1000)
  66.         print "Done!\b\b",
  67.         #关闭文件与连接 
  68.         fwrite.close()
  69.         conn.close()
  70.    
  71. percent = 0
  72. #建立并启动线程
  73. downThread = download("downThread")
  74. downThread.start()

  75. #输出百分比
  76. while percent < 100:
  77.     if percent == 0:
  78.         pass
  79.     elif percent < 10:
  80.         print "%i%%" % percent,
  81.         print "\b\b\b\b",
  82.     else:
  83.         print "%i%%" % percent,
  84.         print "\b\b\b\b\b",
  85.     time.sleep(0.05)
复制代码

[ 本帖最后由 rikioy 于 2006-7-23 18:53 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2006-07-22 14:30 |只看该作者
鼓励!

两个建议:
1. 定义一个main函数,比如:

  1. def main():
  2.   downThread = download("downThread")
  3.   downThread.start()

  4.   #输出百分比
  5.   while percent < 100:
  6.       if percent == 0:
  7.           pass
  8.       elif percent < 10:
  9.           print "%i%%" % percent,
  10.           print "\b\b\b\b",
  11.       else:
  12.           print "%i%%" % percent,
  13.           print "\b\b\b\b\b",
  14.       time.sleep(0.05)
  15. if __name__=='__main__':
  16.   main()
复制代码

这样,万一你的模块被import时,不会启动线程
2. 使用命令行参数,比如指定要下载的页面,文件保存位置什么的

Python cookbook 有一个进度条的例子,你看看
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/299207

[ 本帖最后由 wolfg 于 2006-7-22 14:34 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2006-07-23 18:42 |只看该作者
改进了一些东西,算是第二版吧。希望前辈能提出改进意见。为了在这里显示的好,我在这里改了一下格式。我的PY编辑器用的是NEWEDIT


代码下载
http://www.wowor.org/code/httpdown02.zip



httpdown code

  1. #        _*_ coding:cp936 _*_
  2. """
  3. Name:Sample downloads Program use httplib
  4. Version:0.2
  5. Programe:rikioy
  6. Email:rikiy AT gmail DOT com
  7. Date:2006-07-23
  8. Introduction:这是一个简单的单线程下载程序,下载的是我网站里的一个小游戏,挖金子。PYTHON刚刚接触,书刚看到函数那里,看不下去了,太枯燥了,就试着自己做一个小玩意提提兴趣。 其中肯定有很多问题,比如说比较笨的处理方法,请大家给我指出。
  9. new:过了庸庸碌碌的一天之后,又拿其这个程序继续的改,形成了这个版本。
  10. UseKnowledge:
  11. 1、httplib库的使用,会用就简单多啦。
  12. 2、设置引用页,有些网站下载需要,类似FLASHGET中的设置引用页。其实也是httplib中的知识。
  13. 3、下载进度的计算,这个难道我一个下午,没经验的结果。虽然现在设计的也不好,不能用于多线程,不过以后在改吧。
  14. 4、输出百分比,这个也小难了一会,不过后来找到方法了。用退格。呵呵。
  15. new:5、也没有什么新的,就是在程序里加入了 __name__ 判断。把显示进度单独分出去形成progressNumber类,在类里加入了__doc__。
  16. new:6、把下载类封好了。可以多个进程下载不同的文件。
  17. A pity:
  18. 1、rMsg是要下载文件的总大小,在计算进度的时候 percent = round(totle/fsize*100) 中 fsize 直接用 rMsg是不行的,弄了一下午才找到是这个问题,为什么,还不知道。
  19. 2、文件变量用的比较乱,太晚了,不想整理了。
  20. 3、没有任何异常处理,太脆弱了。
  21. new:4、progressNumber 类还是没有解决好,已经像CU的前辈求救了。其实我也是多余写这个东西,我想在图形界面上就不存在这个问题了。不过还是想知道解决方法。
  22. new:5、没有加入对文件进行分块下载,
  23. Future:
  24. 1、单个文件多进程分块下载。
  25. 2、下载任务考文本文件来配置(目前可以进行程序控制)
  26. 3、支持断点续传。
  27. 4、加入异常处理
  28. Thanks:
  29. BAIDU,我在百度搜索到了很多有用的东西。
  30. GOODNAME008,看了他写的一个简单的关于下载文件的文章,并且不厌其烦地回答我弱智的问题。BLOG,http://blog.csdn.net/goodname008
  31. new:谢谢CU wolfg 的鼓励,有人看并且给自己回应感觉确实不一样啊,也是动力啊。

  32. """

  33. #引入HTTPLIB的库,URLLIB2也可以做个事情,但PY文档里面HTTPLIB介绍的比较多,所以就用这个了
  34. import httplib
  35. #单线程
  36. import threading
  37. #在最后计算下载百分比的时候用到了时间库
  38. import time
  39. #自己写的 显示进度的类
  40. import progressNumber
  41.         

  42. class httpdown(threading.Thread):
  43.     def __init__ (self,threadname,fileurl,filepath,fileobject,filereferer = None):
  44.         """threadname        : Thread name.
  45.            fileurl                : Download file root url.        Example: www.wowor.org
  46.            filepath                : Download file absolute path from root.        Example: /wjz.exe
  47.            fileobject        : Store file name.        Example: wjz.exe
  48.            filereferer        : Set Referer,Reference RFC2616.        Example: http://www.wowor.org
  49.         """
  50.         threading.Thread.__init__(self,name=threadname)
  51.         self.tName = threadname
  52.         self.fUrl = fileurl
  53.         self.fPath = filepath
  54.         self.fObject = fileobject
  55.         self.fReferer = filereferer

  56.     def run(self):
  57.         #设置HTTP连接实例
  58.         conn = httplib.HTTPConnection(self.fUrl)
  59.         #发送GET请求,在httplib中有putrequest和request两种,在MANUALS中有,不能混用。
  60.         conn.putrequest('GET',self.fPath)
  61.         #PUT头,Referer也是设置引用页的地方。
  62.         if self.fReferer:
  63.             conn.putheader('Referer',self.fReferer)
  64.         #PUT header结束,不结束后面进行不了。
  65.         conn.endheaders()
  66.         #得到服务器回应
  67.         rMsg = conn.getresponse()
  68.         #建立文件 fwrite
  69.         fwrite = open(self.fObject,'wb+')
  70.         #total后面计算进度用的,已下载量。
  71.         total = 0
  72.         #取得服务器返回的文件大小,length 文档中好像没有,我在LIB代码中查到的。
  73.         fsize = rMsg.length
  74.         #输出最后加逗号,不换行。
  75.         print "%s download start..." % self.tName,
  76.         #每次读取一千字节放到 ftmp 中
  77.         ftmp = rMsg.read(1000)
  78.         #创建自定义类progressNumber实例,功能:显示下载百分比。具体使用请参看progressNumber类
  79.         pn = progressNumber.progressNumber(fsize)
  80.         #开始循环读,并且 用percent = round(totle/fsize*100)计算百分比
  81.         while len(ftmp):
  82.             fwrite.write(ftmp)
  83.             total = total + len(ftmp)
  84.             pn.progress(total)
  85.             ftmp = rMsg.read(1000)
  86.         print "Done!\b\b"
  87.         #关闭文件与连接 
  88.         fwrite.close()
  89.         conn.close()
  90.    


  91. if __name__ == '__main__':
  92.         #建立并启动线程
  93.         downThread = httpdown("WjzDown","www.wowor.org","/wjz.exe","w.exe")
  94.         downThread.start()

复制代码



progressNumber code

  1. # Class Name: Progress Number Class
  2. #
  3. # Author: rikioy
  4. #
  5. # Email: rikioy at gmail DOT com
  6. #
  7. # Date: 07/23/2006
  8. #
  9. #

  10. class progressNumber:
  11.     "Print prgress number behind the string."
  12.     def __init__( self,finalcount):
  13.         self.finalcount = finalcount
  14.     def progress(self,count):
  15.         "Update the current progress."
  16.         
  17.         count = min(count,self.finalcount)
  18.         if self.finalcount:
  19.             percentcomplete = int(round(100*count/self.finalcount))
  20.         
  21.             if percentcomplete < 10:
  22.                 print "%d%%" % percentcomplete,
  23.                 print "\b\b\b\b",
  24.             else:
  25.                 print "%d%%" % percentcomplete,
  26.                 print "\b\b\b\b\b",
  27.         else:
  28.             pass

  29. if __name__ == '__main__':
  30.     from time import sleep
  31.    
  32.     print "Name          : Class prgressNumber"
  33.     print "Class __doc__ : %s\n" % progressNumber.__doc__
  34.    
  35.     print "Demo."
  36.     #notiec: Add one comma behind the string
  37.     #When you use comma in print,the pring don't output '\n'
  38.     print "Display the progress behind this string.",
  39.     pn = progressNumber(70)
  40.     count = 0
  41.     while count < 70:
  42.         count += 1
  43.         pn.progress(count)
  44.         sleep(0.1)
复制代码

[ 本帖最后由 rikioy 于 2006-7-23 18:56 编辑 ]
西门吹风_CU 该用户已被删除
4 [报告]
发表于 2006-09-07 11:00 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
5 [报告]
发表于 2006-09-09 08:50 |只看该作者
有多线程的版本了。但是控制台输出的问题没法解决。

论坛徽章:
4
CU大牛徽章
日期:2013-03-13 15:29:07CU大牛徽章
日期:2013-03-13 15:29:49CU大牛徽章
日期:2013-03-13 15:30:192015亚冠之广州恒大
日期:2015-07-22 17:20:15
6 [报告]
发表于 2006-09-09 15:24 |只看该作者
如果是多线程的话 因为你是写到磁盘的是同一个文件 所以我觉得 可以用lock 实现多线程 应该没多大问题
当然你也可以不用lock 可以每个线程建一个文件 然后合并 这样要避免重复下在相同的数据 这个文件划分这块 估计就还有点麻烦
用lock还是最简单的

论坛徽章:
0
7 [报告]
发表于 2006-09-13 11:22 |只看该作者
楼主,你的单线程百分比输出正确吗?

论坛徽章:
0
8 [报告]
发表于 2006-09-13 12:16 |只看该作者
sys.stdout.flush()
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP