python + selenium多进程分摊爬虫任务基础

1. 背景

  • 现在有这样一个需求:爬取淘宝商品信息,具体的流程是,在搜索栏输入关键字,然后爬取搜索结果列表中的商品信息。
  • 分析这个需求会发现具有如下特点:
    • 第一,淘宝请求url具有一定的反爬措施,构造起来困难 ——> 应对这种问题的方案就是采用selenium浏览器渲染技术去爬取。
    • 第二,实践发现,目前淘宝对这个爬取频率并没有做很大的限制。也就是说,可以在selenium的基础上,加上多进程并发的方式,并行爬取数据,加快爬取速度。
    • 第三,为什么不用多线程,而选择多进程?由于python GIL的存在,在CPU密集型的程序当中,使用多线程并不能有效利用多核CPU的优势,因为一个解析器在同一时刻只会有一个线程在执行。所以,python的多进程(multiprocessing)模块可以充分利用硬件的多处理器来进行工作。目前支持UNIX和Windows系统。而且multiprocessing提供了本地和远程的并发性。

2. 环境

  • python 3.6.1
  • 系统:win7
  • IDE:pycharm
  • selenium 3.7.0

3. 多进程任务分摊

  • 基本思路:
    • 第一,开多个进程,并行运行多个chrome浏览器。
    • 第二,将所有的关键字放入同一个queue中,其他进程从中获取关键字,进行搜索数据。

import configure
import multiprocessing
import time

# 由mark标记是哪个进程执行的动作
def getkeyWordFunc(queue, lock, mark):
while not queue.empty():
# def get(self, block=True, timeout=None):
keyWord = queue.get()

# 加锁,是为了防止散乱的打印。 保护一些临界状态
# 多个进程运行的状态下,如果同一时刻都调用到print,那么显示的打印结果将会混乱
lock.acquire()
print(f"keyWord = {keyWord}, markProcess = {mark}")
lock.release()
time.sleep(1)

if __name__ == '__main__':
lock = multiprocessing.Lock() # 进程锁
queue = multiprocessing.Queue(150) # 队列,用于存放所有的初始关键字

for keyWord, keyWordValue in configure.keySearchWords.items():
print(f"keyWord = {keyWord}")
# 如果queue定的太小,剩下的放不进去,程序就会block住,等待队列有空余空间
# def put(self, obj, block=True, timeout=None):
queue.put(keyWord)
print(f"queueBefore = {queue}")

getKeyProcessLst = []
# 生成两个进程,并启动
for i in range(2):
# 携带的args 必须是python原有的数据类型,不能是自定义的。否则会出现下面的error(见后面)
process = multiprocessing.Process(target = getkeyWordFunc, args = (queue, lock, i))
process.start()
getKeyProcessLst.append(process)

# 守护线程
# join 等待线程终止,如果不使用join方法对每个线程做等待终止,那么线程在运行过程中,可能会去执行最后的打印
# 如果没有join,父进程就不会阻塞,启动子进程之后,父进程就直接执行最后的打印了
for p in getKeyProcessLst:
p.join()

print(f"queueAfter = {queue}")
queue.close()
print(f"all queue used.")
  • 运行结果:可以看到关键字被分摊到两个进程中去了
queueBefore = <multiprocessing.queues.Queue object at 0x0000000002277F60>
keyWord = 头巾, markProcess = 0
keyWord = 上衣, markProcess = 1
keyWord = 铁碗, markProcess = 0
keyWord = 玩具, markProcess = 1
keyWord = 苹果, markProcess = 0
keyWord = 床单, markProcess = 1
keyWord = 石榴, markProcess = 0
queueAfter = <multiprocessing.queues.Queue object at 0x0000000002277F60>
all queue used.
  • args参数不正确造成的error
queueBefore = <multiprocessing.queues.Queue object at 0x000000000385CCF8>
Traceback (most recent call last):
File "E:/PyCharmCode/taobaoProductSelenium/taobaoSeleniumMulti.py", line 399, in <module>
process.start()
File "E:\Miniconda\lib\multiprocessing\process.py", line 105, in start
self._popen = self._Popen(self)
File "E:\Miniconda\lib\multiprocessing\context.py", line 223, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
File "E:\Miniconda\lib\multiprocessing\context.py", line 322, in _Popen
return Popen(process_obj)
File "E:\Miniconda\lib\multiprocessing\popen_spawn_win32.py", line 65, in __init__
reduction.dump(process_obj, to_child)
File "E:\Miniconda\lib\multiprocessing\reduction.py", line 60, in dump
ForkingPickler(file, protocol).dump(obj)
TypeError: can't pickle _thread.lock objects

更多相关文章

  1. 我需要一个django-芹菜守护进程来监听特定的rabbitmq通道
  2. 使用nagios+python监控nginx进程数
  3. 脚本结束后如何运行进程并退出?
  4. 【好文收藏】理解python多线程
  5. python subprocess模块 监控子进程的2种方式 忙等待和立即返回同
  6. 初探Linux kernel之进程相关二
  7. Linux--多线程之线程的取消pthread_cancel
  8. 检查进程是否仍在运行
  9. Linux多线程——异步

随机推荐

  1. C 语言结构体详解
  2. c语言break和continue用法
  3. C语言--x和x--的区别
  4. c语言中fun用法详解
  5. c++中string类的常用方法有哪些
  6. C++ 引用和指针区别
  7. C语言比较三个数大小
  8. c语言实现输出所有的水仙花数
  9. xcode怎么使用
  10. %ld 在 C 语言中什么意思?