我试图在尽可能短的时间内抓取大量包含JSON格式数据的URL(大约3百万个)。为此,我有一个使用Queue,Multithreading和Urllib3的Python代码(python 3)。在前3分钟内一切正常,然后代码开始减速,然后它似乎完全陷入困境。我已经阅读了我在这个问题上可以找到的所有内容,但不幸的是,解决方案似乎需要一种远远超出我的知识。
我试图限制线程数:它没有修复任何东西。我还尝试限制队列的maxsize并更改套接字超时,但它也没有任何帮助。远程服务器没有阻止我,也没有将我列入黑名单,因为我可以随时重新启动我的脚本,并且在开始时会有很好的结果(代码在相当随机的时间开始变慢)。此外,有时我的互联网连接似乎被削减 - 因为我不能在任何网站上冲浪 - 但这个特定的问题并不是每次都出现。
这是我的代码(请告诉我,我是个笨蛋):
#!/usr/bin/env python
import urllib3,json,csv
from queue import Queue
from threading import Thread
csvFile = open("X.csv", 'wt',newline="")
writer = csv.writer(csvFile,delimiter=";")
writer.writerow(('A','B','C','D'))
def do_stuff(q):
http = urllib3.connectionpool.connection_from_url('http://www.XXYX.com/',maxsize=30,timeout=20,block=True)
while True:
try:
url = q.get()
url1 = http.request('GET',url)
doc = json.loads(url1.data.decode('utf8'))
writer.writerow((doc['A'],doc['B'], doc['C'],doc['D']))
except:
print(url)
finally:
q.task_done()
q = Queue(maxsize=200)
num_threads = 15
for i in range(num_threads):
worker = Thread(target=do_stuff, args=(q,))
worker.setDaemon(True)
worker.start()
for x in range(1,3000000):
if x < 10:
url = "http://www.XXYX.com/?i=" + str(x) + "&plot=short&r=json"
elif x < 100:
url = "http://www.XXYX.com/?i=tt00000" + str(x) + "&plot=short&r=json"
elif x < 1000:
url = "http://www.XXYX.com/?i=0" + str(x) + "&plot=short&r=json"
elif x < 10000:
url = "http://www.XXYX.com/?i=00" + str(x) + "&plot=short&r=json"
elif x < 100000:
url = "http://www.XXYX.com/?i=000" + str(x) + "&plot=short&r=json"
elif x < 1000000:
url = "http://www.XXYX.com/?i=0000" + str(x) + "&plot=short&r=json"
else:
url = "http://www.XXYX.com/?i=00000" + str(x) + "&plot=short&r=json"
q.put(url)
q.join()
csvFile.close()
print("done")
答案 0 :(得分:0)
正如shazow所说,这不是线程的问题,而是每个线程从服务器获取数据的超时。尝试在代码中包含一些时间:
finally:
sleep(50)
q.task_done()
它也可以通过生成自适应超时来改进,例如,您可以测量您成功获得的数据量,如果该数量减少,则增加睡眠时间,反之亦然