本文分为以下几个部分两个线程抓10个网页
线程数量试验
参考资料
线程数量控制
线程池
两个线程抓10个网页
之前我们有过循环抓取10页豆瓣电影数据的例子,当时是每次循环都新建了一个线程,但是如果我们想要只用两个线程怎么办呢?
首先声明,1个线程分5个的想法是不行的,因为每个线程运行时间带有随机性,如果任务平均分配,则很可能出现一个线程还在苦苦工作,而另一个线程已经完成,却无法帮助前一个线程分担的情况,这无疑会降低运行效率。
一个办法是维护一个队列,两个线程都从中获取任务,直到把这个队列中的任务都做完。这个过程其实就是特殊的生产消费模式,只不过没有生产者,任务量是固定的而已。
import threading
import requests
from bs4 import BeautifulSoup
from queue import Queue
class MyThread(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
while not self.queue.empty(): # 如果while True 线程永远不会终止
url = self.queue.get()
print(self.name, url)
url_queue.task_done()
r = requests.get(url)
soup = BeautifulSoup(r.content, 'html.parser')
lis = soup.find('ol', class_='grid_view').find_all('li')
for li in lis:
title = li.find('span', class_="title").text
print(title)
url_queue = Queue()
for i in range(10):
url = 'https://movie.douban.com/top250?start={}&filter='.format(i*25)
url_queue.put(url)
th1 = MyThread(url_queue)
th2 = MyThread(url_queue)
th1.start()
th2.start()
th1.join()
th2.join()
url_queue.join()
print('finish')
这里注意几点Queue.empty()表示如果队列是空则为True,否则是Fals