前言:这几天忙活的做个网页玩玩,网上也没有教程。买个域名又得解析,又得备案,真是麻烦,觉得一个简单的HTML网页应该用不到那么麻烦吧。
昨天又看了几个关于多线程爬虫的例子,觉得很好,提炼出来,总结几个应用模板。
目录
一 多线程Threading模块
1-1 简单的函数创建多线程
## 简单应用thread模块
import socket
import threading
import requests
tasks = []
lock = threading.Lock() # 建立一个锁
# 线程工作函数
def worker(i):
socket.setdefaulttimeout(5) # 设置全局超时时间
try:
r = requests.get(url)
lock.acquire() # 获得锁
print('Processing ',i)
lock.release() # 释放锁
except Exception as e:
lock.acquire()
print(e)
lock.release()
# 多线程
threads = []
for i in range(len(tasks)):
# 参数包括,目标函数,以及操作对象序号
thread = threading.Thread(target=worker, args=[i])
# 将全部IP加入线程,并开始多线程
threads.append(thread)
thread.start()
# 阻塞主进程,等待所有子线程结束
# 通俗的将,就是执行完上述的过程再结束
for thread in threads:
thread.join()
2-1 用类包装线程对象
import threading
import time
class myThread(threading.Thread):
'''
构造方法
'''
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
print("Starting " + self.name)
'''打开网页以及查找等操作
'''
# 获得锁,成功获得锁定后返回True
# 可选的timeout参数不填时将一直阻塞直到获得锁定
# 否则超时后将返回False
threadLock.acquire()
'''保存文件,打印操作
'''
print(self.name, self.counter, 3)
# 释放锁
threadLock.release()
threadLock = threading.Lock()
threads = []
'''创建,开始,添加线程组
'''
for i in range(1,3):
# 创建新线程
thread = myThread(i, "Thread-%s"%i, i)
# 开启新线程
thread.start()
# 添加线程到线程列表
threads.append(thread)
# 等待所有线程完成
for t in threads:
t.join()
print("iting Main Thread")
二 多线程Queue模块
2-1 使用Queue 与 Threading模块
import os
import random
import threading
import time
from queue import Queue
import requests
class myThread(threading.Thread):
def __init__(self,func):
# 调用父类构造函数
super(myThread, self).__init__()
# 传入线程函数逻辑
self.func=func
def run(self):
'''
重写run方法
'''
self.func()
# 功能函数
def worker():
global Q
while not Q.empty():
# 获得任务
item = Q.get()
'''
执行的任务
'''
# 原来写Queue,没有初始化
Q.task_done()
'''其他功能性函数
'''
# 主函数
def main():
global Q
threads = []
# 向队列中放入任务
for task in range(len(tasks)):
Q.put(tasks[task])
# 执行线程
for i in range(thread_num):
thread = myThread(worker)
thread.start()
threads.append(thread)
# 等待线程结束
for thread in threads :
thread.join()
# 等待所有线程结束
Q.join()
# 本项目中执行
if __name__ == '__main__':
# 无限制队列
Q = Queue()
# 线程数
thread_num = 100
# 任务对象列表
tasks = []
start = time.time()
main()
end = time.time()
print('It takes ',end-start)
三 多进程并发模块
3-1 Queue 与 Threading实现并发
# 多线程并发模板
from queue import Queue
from threading import Thread
from time import sleep
#q是任务队列
#NUM是并发线程总数
#JOBS是有多少任务
q = Queue()
NUM = 2
JOBS = 10
#具体的处理函数,负责处理单个任务
def do_somthing_using(arguments):
print(arguments)
#这个是工作进程,负责不断从队列取数据并处理
def working():
while True:
arguments = q.get()
do_somthing_using(arguments)
sleep(1)
q.task_done()
#fork NUM个线程等待队列
for i in range(NUM):
t = Thread(target=working)
t.setDaemon(True)
t.start()
#把JOBS排入队列
for i in range(JOBS):
q.put(i)
#等待所有JOBS完成
q.join()
3-2 multiprocessing模块实现并发
from multiprocessing import Pool
pool = Pool(8)
data_list = pool.map(get, url_list)
pool.close()
pool.join()
后记:
有些并不是很理解,但是可以直接套模板。简单简单点来,可以用类包装Threading模块,但是如果应用对象很多,这样一下子把所有的线程都开了,会卡死,应该有解决办法吧,目前还没查到;然后,如果任务对象很多,就直接用queue模块,只开启一定的线程,依次执行,目前应用的蛮好,再看;最后,关于多进程并发的还不是很清楚,之后在了解吧。期间还看到了协程,等知识不够用了再学。
参考链接:
Python爬虫进阶五之多线程的用法
Python爬虫(五)–多线程续(Queue)
Python爬虫实例2-多线程爬虫抓取糗事百科数据
Python爬虫(四)–多线程