这一个爬取的网站是糗事百科的页面去所有标题!最后是以打印的方式展示的!
这是第二篇文章,多线程的爬取糗事百科所有标题。一共是有三个版本,我一共会发三篇文章!html
第一篇:上篇,正常爬取 糗事百科所有标题
第二篇:本篇,多线程的爬取糗事百科所有标题
第三篇:下篇,多进程的爬取糗事百科所有标题python
# 操做系统:win10 专业版 pycharm professional 2019.1 python 3.8 lxml == 4.5.1 requests == 2.23.0 xpath == 2.0.2
糗事百科的页面所有标题!最后以打印的方式展示!
地址:web
# 页面一共是1-13页 https://www.qiushibaike.com/8hr/page/1/ ...... https://www.qiushibaike.com/8hr/page/13/
图片中的数据就是咱们须要获取的。用xpath这一个获取到了所有咱们须要的!
对于url地址就是1----13这一个简单处理,其余都是简单的爬虫流程,再也不赘述!具体看代码的注释吧!
再看一哈思路!网络
思路:
1.建立数据容器对象
URL容器
HTML容器
数据容器
2.实现处理任务函数
实现生产URL任务
实现消费URL生产HTML任务
实现消费HTML生产数据任务
实现消费数据任务
3.让任务函数运行在线程上,并以守护线程的形式运行多线程4.主线程退出条件app
5.调整线程数量实现并行执行svg
“”"函数
# put的时候计数+1,get不会-1,get须要和task_done 一块儿使用才会-1 from queue import Queue # 构建队列 # maxsize=100 最大容量100 q = Queue(maxsize=100) item = { } # 把数据放入到队列中,若是队列数据已满,就进行等待直到队列不满时把数据添加到队列中 q.put(item) # 把数据放入到队列中,若是队列数据已满,就不进行等待,引起异常 q.put_nowait(item) # 把数据从队列中取出,若是队列为空,就进行等待直到队列不为空,返回数据 q.get() # 把数据从队列中取出,若是队列为空,就不进行等待,引起异常 q.get_nowait() # 获取队列中元素个数 q.qsize() # 获取未完成的任务数 q.unfinished_tasks # 让 unfinished_tasks 属性 -1 q.task_done() # 当前程序进行等待状态,直到队列的 unfinished_tasks 属性为 0 时继续执行 q.join()
注意:学习
put
或 put_nowait
方法时 q.qsize()
会 + 1
,而且 q.unfinished_tasks
也会 + 1
get
或 get_nowait
方法时 q.qsize()
会 -1
,可是 unfinished_tasks
不发生变化task_done
方法时 unfinished_tasks
会 -1
# 建立线程对象 t1 = threading.Thread(target=func,args=(,)) # 设置为守护线程 t1.setDaemon(True) # 启动线程 t1.start()
咱们直接写代码了!网站
import requests from lxml import etree from threading import Thread from queue import Queue import time class QiushiThread(): """糗事百科多线程爬虫""" def __init__(self): # 构建请求头 self.headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36" } # 构建基础的url地址 self.baseurl = "https://www.qiushibaike.com/8hr/page/{}/" # 建立url队列容器 self.url_queue = Queue() # 建立html队列容器 self.html_queue = Queue() # 建立数据队列容器 self.data_queue = Queue() # 1.构建url地址 def url_list(self): """ :return: 目标url列表 """ # 一共13页 for i in range(1,14): # 获取到url url = self.baseurl.format(i) # 把url添加到队列中 self.url_queue.put(url) # print(f"如今开始请求第 {i} 页码") # 2.发送请求获取数据 def send_requests(self): # 循环的取出url,发送请求,直到任务所有完成 # 完成标志:Thread().unfinished_task 值为0 while True: # 一、从队列中取出url url = self.url_queue.get() # 打印请求的页面url print(url) # 2.发送请求获取html页面数据--网络延迟 response = requests.get(url=url,headers=self.headers) html = response.content.decode() # 把html页面添加到队列中,html_queue任务数量+1 self.html_queue.put(html) # 这时候url_queue的任务数量完成,就要-1 self.url_queue.task_done() # 3.从响应中提取数据 def get_response(self): # 循环的取出url,发送请求,直到任务所有完成 # 完成标志:Thread().unfinished_task 值为0 while True: # 从html_queue队列中获取响应 responsehtml = self.html_queue.get() # 获取响应数据 html = etree.HTML(responsehtml) restitle_list = html.xpath("//li//a[@class='recmd-content']/text()") # 把获取到的数据添加到数据任务队列data_queue,任务数量加一,+1 self.data_queue.put(restitle_list) # 同时html_queue队列任务减小一个 -1 self.html_queue.task_done() # 保存数据 def save(self): while True: # 从数据队列中取出数据 resdata_list = self.data_queue.get() # print(resdata_list) for resdata in resdata_list: print(resdata) # 通知数据队列任务完成 self.data_queue.task_done() # 执行 def run(self): thread_list = [] # 建立 获取 url 的任务线程,而且添加到列表 url_thread = Thread(target=self.url_list) thread_list.append(url_thread) # 建立发送resquest请求 获取 html 的任务线程,而且添加到列表 html_thread = Thread(target=self.send_requests) thread_list.append(html_thread) # 建立 获取 数据响应数据 的任务线程,而且添加到列表 data_thread = Thread(target=self.get_response) thread_list.append(data_thread) # 建立 保存数据 的任务线程,而且添加到列表 save_thread = Thread(target=self.save) thread_list.append(save_thread) # 开启线程守护 for thread_item in thread_list: # 开启线程守护,主进程结束,子进程也结束 thread_item.setDaemon(True) # 开始子线程 thread_item.start() # 睡眠,防止太快! # 保证子线程必定能执行 time.sleep(2) # 同时队列中的所有任务执行完毕,才结束程序 for queueitem in [self.url_queue,self.html_queue,self.data_queue]: # 若是没有完成的任务不是0,就是表明还有任务没有完成,就要任务继续在等待的状态,等待任务执行 # 每一个任务函数中都有task_done返岗,任务数量,每次执行都会-1 queueitem.join() if __name__ == '__main__': obj1 = QiushiThread() obj1.run()
最后获取的信息是以打印的方式展示的!
我的记录,新手入门,多多学习,欢迎你们交流探讨!
我的网站: http://106.54.78.238/
song_of _sea的我的网站 http://106.54.78.238/