当我问这个问题时,如果我看起来像个菜鸟,那是因为这是我第一次尝试多线程。遗憾。
看到多线程是为了让这个过程更快,我试图弄清楚我在哪里出错了。我注意到的第一件事是“主线程”线程比应该的速度慢得多(它是唯一不使用代理的线程)。
在进程多线程之前,它会在一个进程/线程中在一分钟内下载大约10-15个图像。但现在,“多线程”(这是唯一一个不通过代理发送HTTP请求的人)实际上从未显示过(正如您所见:http://puu.sh/3KfwY.png)。它应该是最快的线程!
我希望我能清楚地解释我的问题。 :S
P.S:在节目开始时,它会在15秒内下载约20张图片;然而,在初次启动之后,程序急剧减速。关于这是为什么的任何想法?
#!/usr/bin/env python
import sys
import string
import os.path
import urllib.request
import threading
from time import gmtime, strftime, sleep
from random import choice
#list of our proxies
proxies = []
downloads = 1
#the number of files we want to download
target = int(sys.argv[1])
#argument 2 - proxies
try:
sys.argv[2]
except:
print('')
else:
param = sys.argv[2]
if param.find('.txt') != -1:
print('Loading specified proxy list ('+ param +').')
f = open(param, 'r+')
print('Opening '+ f.name)
proxylist = f.read()
f.close()
#split retrieved list by new line
proxies = proxylist.split('\n')
else:
print('Single proxy specified.')
proxies.append(param)
class thread(threading.Thread):
def __init__(self, ID, name, proxy):
threading.Thread.__init__(self)
self.id = ID
self.name = name
self.downloads = 0
self.proxy = proxy
self.running = True
self.fails = 0
def run(self):
global downloads
if self.proxy != False:
#id is always above one, so make the ID -1
self.proxy = proxies[(self.id-1)]
print(self.name +' initiating with proxy: '+self.proxy)
#make our requests go through proxy
self.p_handler = urllib.request.ProxyHandler({'http' : self.proxy})
self.opener = urllib.request.build_opener(self.p_handler)
urllib.request.install_opener(self.opener)
else:
print(self.name +' initiating without a proxy.')
while downloads <= target and self.running:
rstr = ''.join(choice(string.ascii_letters + string.digits) for x in range(5))
url = 'http://puu.sh/'+rstr
filename = 'downloaded/'+ strftime('%Y %m %d %H-%M-%S', gmtime()) +'.png';
try:
urllib.request.urlretrieve(url, filename)
except urllib.request.HTTPError:
pass
except IOError:
if self.fails > 10:
print(self.name +': Proxy is not working. Stopping thread.')
self.running = False
self.fails += 1
except:
pass
else:
print(self.name +': downloading '+ filename+'...' + str(downloads))
#if self.downloads % 10 == 0:
# print(self.name +': Sleeping a bit.')
# sleep(60)
downloads += 1
self.downloads += 1
sleep(5)
#lets create the "downloaded" folder if it does not exist
if not os.path.isdir('downloaded'):
try:
os.mkdir('downloaded')
except:
pass
#thread count
thread_count = 1
#create threads, and initiate them
try:
thread(0, 'main-thread', False).start()
for x in proxies:
thread(thread_count, 'Thread-'+str(thread_count), proxies[(thread_count-1)]).start()
thread_count += 1
except:
print('Couldn\'t start threads.')
答案 0 :(得分:0)
我不知道实际问题是什么,但我注意到的一件事是你使用urllib.request.install_opener
。这设置了默认的全局开启者,因此每个线程都会看到更改。这可能是第一次通过,大多数线程使用它们被分配的代理,但之后,所有请求都转到同一个代理,并且您受到代理或其他东西的限制。
sleep(5)
看起来很奇怪。这很容易成为你的问题。
您正在使用没有锁定的共享全局变量。它可能不会在大多数时候咬你,但你最终可能会遇到奇怪的失败,除非你正确地同步从不同线程同时访问可变状态。