本来想写一个按广度优先爬取所有qq的一些信息和说说,计划线程池来实现多线程
思路:待爬取队列出对200个qq,待爬取队列的组成元素是元组, 即(qq1, depth)
局部代码如下
#开始出队20线程爬数据,这里不使用threading的原因是每次出队20个线程执行都要join,20个线程中只要还剩一个没执行完,在其他的都要
#等,效率太慢
while waiting_get.qsize() >= 200:
#一次性出队200个,然后放入线程池
wating_qq_list = []
for i in range(200):
wating_qq_list.append(waiting_get.get())
print(wating_qq_list)
pool_size = 20
pool = threadpool.ThreadPool(pool_size)
# 创建工作请求
reqs = threadpool.makeRequests(self.get_data, wating_qq_list)
# 将工作请求放入队列
[pool.putRequest(req) for req in reqs]
pool.wait()
这是就会报错:
result = request.callable(*request.args, **request.kwds)
TypeError: get_data() argument after ** must be a mapping, not int
然后研究了下threadpool的源码,
for item in args_list:
if isinstance(item, tuple):
requests.append(
WorkRequest(callable_, item[0], item[1], callback=callback,
exc_callback=exc_callback)
)
else:
requests.append(
WorkRequest(callable_, [item], None, callback=callback,
exc_callback=exc_callback)
)
return requests
发现threadPool包会对传入数据进行验证,如果传入的是个元组数据,那么他会把元组数据分开,做另外处理,元组中第一个元素为请求值,即给请求函数调用的值,第二个元素是结果值,就是请求函数执行后的输出值。
如果第二个元素是其它值,则会报错
那么把元组类型改成list就行啦
踩的巨坑,官方手册都没有说明,拿本小本本记下来