我使用多处理模型开发了一个爬虫。
使用multiprocessing.Queue存储需要抓取的url-infos,需要解析的页面内容等等;使用multiprocessing.Event控制子进程;使用multiprocessing.Manager.dict存储已爬网URL的哈希值;每个multiprocessing.Manager.dict实例都使用multiprocessing.Lock来控制访问。
所有三个类型参数在所有子进程和父进程之间共享,并且所有参数都在一个类中组织,我使用类的实例将共享参数从父进程传输到子进程。就像:
MGR = SyncManager()
class Global_Params():
Queue_URL = multiprocessing.Queue()
URL_RESULY = MGR.dict()
URL_RESULY_Mutex = multiprocessing.Lock()
STOP_EVENT = multiprocessing.Event()
global_params = Global_Params()
在我自己的超时机制中,我使用process.terminate来停止长时间无法自行停止的进程!
在我的测试用例中,有超过2500个目标站点(有些是非服务的,有些是巨大的)。 按站点在目标站点文件中抓取站点。
在开始时爬行器可以正常工作,但经过很长一段时间(有时8小时,有时2小时,有时甚至是15小时),爬行器爬行的距离超过100(这是不确定的)站点,我&#39 ; ll得到错误信息:" Errno 32断管"
我尝试了以下方法来定位和解决问题:
网站定位哪个抓取工具断了,然后使用抓取工具分别抓取网站,抓取工作得很好。即使我从包含站点A的所有目标站点文件中获取了一个片段(例如20个站点),但爬虫也运行良好!
添加" -X / tmp / pymp- * 240 / tmp"到/etc/cron.daily/tmpwatch
发生破坏时文件/ tmp / pymp- *仍然存在
使用multiprocessing.managers.SyncManager替换multiprocessing.Manager并忽略除SIGKILL和SIGTERM之外的大多数信号
对于每个目标站点,我清除了大多数共享参数(队列,dicts和事件),如果发生错误,则创建一个新实例:
while global_params.Queue_url.qsize()>0:
try:
global_params.Queue_url.get(block=False)
except Exception,e:
print_info(str(e))
print_info("Clear Queue_url error!")
time.sleep(1)
global_params.Queue_url = Queue()
pass
以下是Traceback信息,print_info函数定义为自己打印和存储调试信息:
[Errno 32] Broken pipe
Traceback (most recent call last):
File "Spider.py", line 613, in <module>
main(args)
File "Spider.py", line 565, in main
spider.start()
File "Spider.py", line 367, in start
print_info("STATIC_RESULT size:%d" % len(global_params.STATIC_RESULT))
File "<string>", line 2, in __len__
File "/usr/local/python2.7.3/lib/python2.7/multiprocessing/managers.py", line 769, in _callmethod
kind, result = conn.recv()
EOFError
我无法理解为什么,有人知道原因吗?
答案 0 :(得分:1)
我不知道这是否可以解决您的问题,但有一点值得一提:
global_params.Queue_url.get(block=False)
...如果队列为空,则抛出Queue.Empty命令。为空例外重新创建队列是不值得的。
重新排队可能会导致竞争条件。
从我的角度来看,你必须有可能:
使用:
from Queue import Queue
而不是:
from multiprocessing import Queue