简单分布式爬虫-windows环境

创建服务进程
1.建立队列Queue,用来进行进程间通信
2.把第一步建立的队列在网络上注册,暴露给其他进程(主机),注册后获得网络队列,相当于本地队列的映像
3.建立一个对象(Queuemanager(BaseManager))实例manager,绑定端口和验证口令
4.启动第三步中建立的实例,即启动管理manager, 监管信息通道
5. 通过管理实例的方法获得通过网络访问的Queue 对象,即再把网络队列实体化成可以使用的本地队列
6.创建任务到“本地”队列中,自动上传任务到网络队列中,分配给任务进程进行处理

代码如下taskManager_win.py:
import random, time
from multiprocessing import Queue
from multiprocessing.managers import BaseManager
from multiprocessing import freeze_support


# 任务个数
task_number = 10

# 第一步: 建立task_queue和result_queue, 用来存放任务和结果
task_queue = Queue()
result_queue = Queue()

def get_task():
    return task_queue

def get_result():
    return result_queue

# 创建QueueManager
class Queuemanager(BaseManager):
    pass

def win_run():
    # Windows下绑定调用接口不能使用lambda, 所以只能先定义函数再绑定
    # 第二步: 把创建的两个队列注册在网络上,利用register方法,callable参数关联了Queue对象,并将Queue对象在网络上暴露
    Queuemanager.register('get_task_queue', callable=get_task)
    Queuemanager.register('get_result_queue', callable=get_result)


    # 第三步:绑定端口8001,设置验证口令'chongyun',这相当于对象的初始化,windows下需要填写IP地址,Linux下不填默认为本地
    manager = Queuemanager(address=('127.0.0.1', 8001), authkey='chongyun'.encode('utf-8'))

    # 第四步,启动管理,监听信息通道
    manager.start()
    try:
        # 第五步:通过管理实例的方法获得通过网络访问的Queue对象
        task = manager.get_task_queue()
        result = manager.get_result_queue()

        # 第六步:添加任务
        for url in ["ImageUrl_"+str(i) for i in range(10)]:
            print('put task %s ...' % url)
            task.put(url)
        # 获取返回结果
        print('try get result...')
        for i in range(10):
            print('result is %s' % result.get(timeout=10))
    except Exception as e:
        print(e)
    finally:
        # 关闭管理
        manager.shutdown()

if __name__ == '__main__':
    # Windows 下多进程可能会有问题,添加这句可以缓解
    freeze_support()

    win_run()

创建任务进程:
1.使用 QueueManager 注册用于获取Queue的方法名称,任务进程只能通过名称来在网络上获取Queue
2.连接服务器, 端口和验证口令注意保持与服务进程中完全一致
3.从网络上获取Queue,进行本地化

4.从task队列获取任务,并把结果写入result队列

代码如下taskWorker.py:
import time
from multiprocessing.managers import BaseManager

# 创建类似的QueueManager:
class QueueManager(BaseManager):
    pass

# 第一步:使用QueueManager注册用于获取Queue的方法名称
QueueManager.register('get_task_queue')

QueueManager.register('get_result_queue')

# 第二步:连接到服务器
server_addr = '127.0.0.1'
print('Connect to server %s....' % server_addr)
# 端口和验证口令注意保持和服务进程完全一致
m = QueueManager(address=(server_addr, 8001), authkey='chongyun'.encode('utf-8'))
# 从网络连接
m.connect()
# 第三步: 获取Queue的对象
task = m.get_task_queue()
result = m.get_result_queue()
# 第四步: 从task队列获取任务,并把结果写入result队列
while(not task.empty()):
    image_url = task.get(True, timeout=5)
    print('run task download %s...' % image_url)
    time.sleep(1)
    result.put('%s ---> sucess' % image_url)

# 处理结束

print('worker exit.')


先运行taskManager_win.py,运行结果:
put task ImageUrl_0 ...
put task ImageUrl_1 ...
put task ImageUrl_2 ...
put task ImageUrl_3 ...
put task ImageUrl_4 ...
put task ImageUrl_5 ...
put task ImageUrl_6 ...
put task ImageUrl_7 ...
put task ImageUrl_8 ...
put task ImageUrl_9 ...

try get result...

再运行taskWorker.py,显示运行结果:
Connect to server 127.0.0.1....
run task download ImageUrl_0...
run task download ImageUrl_1...
run task download ImageUrl_2...
run task download ImageUrl_3...
run task download ImageUrl_4...
run task download ImageUrl_5...
run task download ImageUrl_6...
run task download ImageUrl_7...
run task download ImageUrl_8...
run task download ImageUrl_9...

worker exit.

同时taskManager_win.py运行结果继续显示
try get result...
result is ImageUrl_0 ---> sucess
result is ImageUrl_1 ---> sucess
result is ImageUrl_2 ---> sucess
result is ImageUrl_3 ---> sucess
result is ImageUrl_4 ---> sucess
result is ImageUrl_5 ---> sucess
result is ImageUrl_6 ---> sucess
result is ImageUrl_7 ---> sucess
result is ImageUrl_8 ---> sucess
result is ImageUrl_9 ---> sucess

Process finished with exit code 0

其中需要注意的事项有:

1. 如果Queue导入 为from queue import Queue

 则可能报错 python TypeError: can't pickle _thread.RLock objects

解决方法:这是因为queue.Queue()是线程的原因,需要把import queue改成from multiprocessing import Queue,然后用Queue()换掉queue.Queue()

2.   TypeError: string argument without an encoding

解决方法: 在字符串后加上.encode('utf-8')

3. TypeError: 'Queue' object is not callable
解决方法:检查"callable="后的函数名是否错误,以及函数调用是否多加了().

你可能感兴趣的:(python基础知识)