最近在工作上需要进行一个爬虫的演示,需要在界面上输入账号,密码,然后开始爬取数据,需要使用多进程爬虫以加快爬取速度,之前一直没用过多进程,Pycharm可以跑,但需要在jupyter上运行(Pycharm使用不了getpass隐藏输入),所以今天写代码时候遇到了不少问题,在此总结一下。
python版本3.7.6
jupyter lab版本1.2.6
①jupyter notebook/lab中直接使用多进程的话,虽然在界面上不会报错,但一直会处于运行状态,去查看命令行的话会看到报错:
AttributeError: Can’t get attribute ‘XXX’ on <module ‘main’ >,由于某些原因Pool不能始终使用未在导入的模块中定义的对象。
②运行时报错:
AttributeError: module ‘main’ has no attribute ‘spec’,这时需要在if name == ‘main’:下面加上:
spec = “ModuleSpec(name=‘builtins’, loader=<class ‘_frozen_importlib.BuiltinImporter’>)”
jupyter只能跟踪主进程,没法跟踪子进程,网上有一些其他的解决办法,但个人觉得最简单的还是将代码打包成py文件,再让jupyter执行这个文件,代码如下:
因为爬虫需要输入账号,密码获取cookie,所以这里为了测试写了个函数输入账号,然后传入worker和main函数中,看是否能正常运行
%%writefile test.py
import os,time
from multiprocessing import Pool
from tqdm import tqdm
import getpass
import time
def user_info():
user = input('请输入用户名:')
psw = getpass.getpass('请输入密码:')#隐藏密码
return user,psw
def worker(x,user,psw):
return x*x
def main(user,psw):
lst = []
print("主进程开始执行>>> pid={}".format(os.getpid()))
ps=Pool(processes=12)
with tqdm(total=len(range(500))) as t:
for i in range(500):
res = ps.apply_async(worker,args=(i,user,psw)) # 异步执行,args为传入的参数
print(res.get())#输出worker计算的结果
#print(i)
t.update()
time.sleep(0.1)
# 关闭进程池,停止接受其它
ps.close()
# 阻塞进程
ps.join()
print("主进程终止")
if __name__ == '__main__':
user,psw = user_info()
print(user)
__spec__ = "ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>)"#
main(user,psw)
执行上面代码会在默认路径下生成一个.py文件
然后再run一:下
%run test.py
大功告成!