(转)写了一个简单的下载程序(23/07/2006更新)
#这是一个简单的单线程下载程序,下载的是我网站里的一个小游戏,挖金子。PYTHON刚刚接触,书刚看到函数那里,看不下去了,太枯燥了,就试着自己做一个小玩意提提兴趣。
#其中肯定有很多问题,比如说比较笨的处理方法,请大家给我指出。
[ 本帖最后由 rikioy 于 2006-7-23 18:53 编辑 ]
wolfg 回复于:2006-07-22 14:30:06
鼓励!
两个建议:
1. 定义一个main函数,比如:
这样,万一你的模块被import时,不会启动线程
2. 使用命令行参数,比如指定要下载的页面,文件保存位置什么的
Python cookbook 有一个进度条的例子,你看看
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/299207
[ 本帖最后由 wolfg 于 2006-7-22 14:34 编辑 ]
rikioy 回复于:2006-07-23 18:42:33
改进了一些东西,算是第二版吧。希望前辈能提出改进意见。为了在这里显示的好,我在这里改了一下格式。我的PY编辑器用的是NEWEDIT
代码下载
[url=http://www.wowor.org/code/httpdown02.zip]http://www.wowor.org/code/httpdown02.zip
httpdown code
progressNumber code
[ 本帖最后由 rikioy 于 2006-7-23 18:56 编辑 ]
西门吹风_CU 回复于:2006-09-07 11:00:24
不错,学习到了一些库的经验,希望能看到搂主多线程和支持exception的版本:)
rikioy 回复于:2006-09-09 08:50:16
有多线程的版本了。但是控制台输出的问题没法解决。
ghostwwl 回复于:2006-09-09 15:24:34
如果是多线程的话 因为你是写到磁盘的是同一个文件 所以我觉得 可以用lock 实现多线程 应该没多大问题
当然你也可以不用lock 可以每个线程建一个文件 然后合并 这样要避免重复下在相同的数据 这个文件划分这块 估计就还有点麻烦
用lock还是最简单的
chopin1998 回复于:2006-09-13 11:22:47
楼主,你的单线程百分比输出正确吗?
chopin1998 回复于:2006-09-13 12:16:20
sys.stdout.flush()
#其中肯定有很多问题,比如说比较笨的处理方法,请大家给我指出。
# _*_ coding:cp936 _*_
#Sample downloads Program use httplib
#Programer:rikioy
#email:rikiy at gmail.com
#date:2006-07-21
#introduction:
#这是一个简单的单线程下载程序,下载的是我网站里的一个小游戏,挖金子。PYTHON刚刚接触,书刚看到函数那里,看不下去了,太枯燥了,就试着自己做一个小玩意提提兴趣。
#其中肯定有很多问题,比如说比较笨的处理方法,请大家给我指出。
#用到的知识主要有:
#1、httplib库的使用,会用就简单多啦。
#2、设置引用页,有些网站下载需要,类似FLASHGET中的设置引用页。其实也是httplib中的知识。
#3、下载进度的计算,这个难道我一个下午,没经验的结果。虽然现在设计的也不好,不能用于多线程,不过以后在改吧。
#4、输出百分比,这个也小难了一会,不过后来找到方法了。用退格。呵呵。
#遗憾:
#1、rMsg是要下载文件的总大小,在计算进度的时候 percent = round(totle/fsize*100) 中 fsize 直接用 rMsg是不行的,弄了一下午才找到是这个问题,为什么,还不知道。
#2、文件变量用的比较乱,太晚了,不想整理了。
#3、没有任何异常处理,太脆弱了。
#改进:
#1、改成多进程的。
#2、下载任务考文本文件来配置
#3、整理程序中的变量与结构,使之更合理。
#4、加入异常处理
#感谢:
#BAIDU,我在百度搜索到了很多有用的东西。
#GOODNAME008,看了他写的一个简单的关于下载文件的文章,并且不厌其烦地回答我弱智的问题。BLOG,http://blog.csdn.net/goodname008
#
#
#引入HTTPLIB的库,URLLIB2也可以做个事情,但PY文档里面HTTPLIB介绍的比较多,所以就用这个了
import httplib
#单线程
import threading
#在最后计算下载百分比的时候用到了时间库
import time
class download(threading.Thread):
def __init__ (self,threadname):
threading.Thread.__init__(self,name=threadname)
def run(self):
#设置HTTP连接实例
conn = httplib.HTTPConnection("www.wowor.org")
#发送GET请求,在httplib中有putrequest和request两种,在MANUALS中有,不能混用。
conn.putrequest('GET','/wjz.exe')
#PUT头,Referer也是设置引用页的地方。
conn.putheader('Referer','http://bbs.pingshu8.com')
#PUT header结束,不结束后面进行不了。
conn.endheaders()
#得到服务器回应
rMsg = conn.getresponse()
#建立文件 fwrite
fwrite = open('wjz.exe','wb+')
#total后面计算进度用的,已下载量。
totle = 0.00
#全局变量 percent = 百分比
global percent
#取得服务器返回的文件大小,length 文档中好像没有,我在LIB代码中查到的。
fsize = rMsg.length
#输出最后加逗号,不换行。
print "Thread download start...",
#每次读取一千字节放到 ftmp 中
ftmp = rMsg.read(1000)
#开始循环读,并且 用percent = round(totle/fsize*100)计算百分比
while len(ftmp):
fwrite.write(ftmp)
totle = totle + len(ftmp)
percent = totle/fsize*100
ftmp = rMsg.read(1000)
print "Done!\b\b",
#关闭文件与连接
fwrite.close()
conn.close()
percent = 0
#建立并启动线程
downThread = download("downThread")
downThread.start()
#输出百分比
while percent < 100:
if percent == 0:
pass
elif percent < 10:
print "%i%%" % percent,
print "\b\b\b\b",
else:
print "%i%%" % percent,
print "\b\b\b\b\b",
time.sleep(0.05)
[ 本帖最后由 rikioy 于 2006-7-23 18:53 编辑 ]
wolfg 回复于:2006-07-22 14:30:06
鼓励!
两个建议:
1. 定义一个main函数,比如:
def main():
downThread = download("downThread")
downThread.start()
#输出百分比
while percent < 100:
if percent == 0:
pass
elif percent < 10:
print "%i%%" % percent,
print "\b\b\b\b",
else:
print "%i%%" % percent,
print "\b\b\b\b\b",
time.sleep(0.05)
if __name__=='__main__':
main()
这样,万一你的模块被import时,不会启动线程
2. 使用命令行参数,比如指定要下载的页面,文件保存位置什么的
Python cookbook 有一个进度条的例子,你看看
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/299207
[ 本帖最后由 wolfg 于 2006-7-22 14:34 编辑 ]
rikioy 回复于:2006-07-23 18:42:33
改进了一些东西,算是第二版吧。希望前辈能提出改进意见。为了在这里显示的好,我在这里改了一下格式。我的PY编辑器用的是NEWEDIT
代码下载
[url=http://www.wowor.org/code/httpdown02.zip]http://www.wowor.org/code/httpdown02.zip
httpdown code
# _*_ coding:cp936 _*_
"""
Name:Sample downloads Program use httplib
Version:0.2
Programe:rikioy
Email:rikiy AT gmail DOT com
Date:2006-07-23
Introduction:这是一个简单的单线程下载程序,下载的是我网站里的一个小游戏,挖金子。PYTHON刚刚接触,书刚看到函数那里,看不下去了,太枯燥了,就试着自己做一个小玩意提提兴趣。 其中肯定有很多问题,比如说比较笨的处理方法,请大家给我指出。
new:过了庸庸碌碌的一天之后,又拿其这个程序继续的改,形成了这个版本。
UseKnowledge:
1、httplib库的使用,会用就简单多啦。
2、设置引用页,有些网站下载需要,类似FLASHGET中的设置引用页。其实也是httplib中的知识。
3、下载进度的计算,这个难道我一个下午,没经验的结果。虽然现在设计的也不好,不能用于多线程,不过以后在改吧。
4、输出百分比,这个也小难了一会,不过后来找到方法了。用退格。呵呵。
new:5、也没有什么新的,就是在程序里加入了 __name__ 判断。把显示进度单独分出去形成progressNumber类,在类里加入了__doc__。
new:6、把下载类封好了。可以多个进程下载不同的文件。
A pity:
1、rMsg是要下载文件的总大小,在计算进度的时候 percent = round(totle/fsize*100) 中 fsize 直接用 rMsg是不行的,弄了一下午才找到是这个问题,为什么,还不知道。
2、文件变量用的比较乱,太晚了,不想整理了。
3、没有任何异常处理,太脆弱了。
new:4、progressNumber 类还是没有解决好,已经像CU的前辈求救了。其实我也是多余写这个东西,我想在图形界面上就不存在这个问题了。不过还是想知道解决方法。
new:5、没有加入对文件进行分块下载,
Future:
1、单个文件多进程分块下载。
2、下载任务考文本文件来配置(目前可以进行程序控制)
3、支持断点续传。
4、加入异常处理
Thanks:
BAIDU,我在百度搜索到了很多有用的东西。
GOODNAME008,看了他写的一个简单的关于下载文件的文章,并且不厌其烦地回答我弱智的问题。BLOG,http://blog.csdn.net/goodname008
new:谢谢CU wolfg 的鼓励,有人看并且给自己回应感觉确实不一样啊,也是动力啊。
"""
#引入HTTPLIB的库,URLLIB2也可以做个事情,但PY文档里面HTTPLIB介绍的比较多,所以就用这个了
import httplib
#单线程
import threading
#在最后计算下载百分比的时候用到了时间库
import time
#自己写的 显示进度的类
import progressNumber
class httpdown(threading.Thread):
def __init__ (self,threadname,fileurl,filepath,fileobject,filereferer = None):
"""threadname : Thread name.
fileurl : Download file root url. Example: www.wowor.org
filepath : Download file absolute path from root. Example: /wjz.exe
fileobject : Store file name. Example: wjz.exe
filereferer : Set Referer,Reference RFC2616. Example: http://www.wowor.org
"""
threading.Thread.__init__(self,name=threadname)
self.tName = threadname
self.fUrl = fileurl
self.fPath = filepath
self.fObject = fileobject
self.fReferer = filereferer
def run(self):
#设置HTTP连接实例
conn = httplib.HTTPConnection(self.fUrl)
#发送GET请求,在httplib中有putrequest和request两种,在MANUALS中有,不能混用。
conn.putrequest('GET',self.fPath)
#PUT头,Referer也是设置引用页的地方。
if self.fReferer:
conn.putheader('Referer',self.fReferer)
#PUT header结束,不结束后面进行不了。
conn.endheaders()
#得到服务器回应
rMsg = conn.getresponse()
#建立文件 fwrite
fwrite = open(self.fObject,'wb+')
#total后面计算进度用的,已下载量。
total = 0
#取得服务器返回的文件大小,length 文档中好像没有,我在LIB代码中查到的。
fsize = rMsg.length
#输出最后加逗号,不换行。
print "%s download start..." % self.tName,
#每次读取一千字节放到 ftmp 中
ftmp = rMsg.read(1000)
#创建自定义类progressNumber实例,功能:显示下载百分比。具体使用请参看progressNumber类
pn = progressNumber.progressNumber(fsize)
#开始循环读,并且 用percent = round(totle/fsize*100)计算百分比
while len(ftmp):
fwrite.write(ftmp)
total = total + len(ftmp)
pn.progress(total)
ftmp = rMsg.read(1000)
print "Done!\b\b"
#关闭文件与连接
fwrite.close()
conn.close()
if __name__ == '__main__':
#建立并启动线程
downThread = httpdown("WjzDown","www.wowor.org","/wjz.exe","w.exe")
downThread.start()
progressNumber code
# Class Name: Progress Number Class
#
# Author: rikioy
#
# Email: rikioy at gmail DOT com
#
# Date: 07/23/2006
#
#
class progressNumber:
"Print prgress number behind the string."
def __init__( self,finalcount):
self.finalcount = finalcount
def progress(self,count):
"Update the current progress."
count = min(count,self.finalcount)
if self.finalcount:
percentcomplete = int(round(100*count/self.finalcount))
if percentcomplete < 10:
print "%d%%" % percentcomplete,
print "\b\b\b\b",
else:
print "%d%%" % percentcomplete,
print "\b\b\b\b\b",
else:
pass
if __name__ == '__main__':
from time import sleep
print "Name : Class prgressNumber"
print "Class __doc__ : %s\n" % progressNumber.__doc__
print "Demo."
#notiec: Add one comma behind the string
#When you use comma in print,the pring don't output '\n'
print "Display the progress behind this string.",
pn = progressNumber(70)
count = 0
while count < 70:
count += 1
pn.progress(count)
sleep(0.1)
[ 本帖最后由 rikioy 于 2006-7-23 18:56 编辑 ]
西门吹风_CU 回复于:2006-09-07 11:00:24
不错,学习到了一些库的经验,希望能看到搂主多线程和支持exception的版本:)
rikioy 回复于:2006-09-09 08:50:16
有多线程的版本了。但是控制台输出的问题没法解决。
ghostwwl 回复于:2006-09-09 15:24:34
如果是多线程的话 因为你是写到磁盘的是同一个文件 所以我觉得 可以用lock 实现多线程 应该没多大问题
当然你也可以不用lock 可以每个线程建一个文件 然后合并 这样要避免重复下在相同的数据 这个文件划分这块 估计就还有点麻烦
用lock还是最简单的
chopin1998 回复于:2006-09-13 11:22:47
楼主,你的单线程百分比输出正确吗?
chopin1998 回复于:2006-09-13 12:16:20
sys.stdout.flush()