Python如何使用队列方式实现多线程爬虫


Posted in Python onMay 12, 2020

说明:糗事百科段子的爬取,采用了队列和多线程的方式,其中关键点是Queue.task_done()、Queue.join(),保证了线程的有序进行。

代码如下

import requests
from lxml import etree
import json
from queue import Queue
import threading

class Qsbk(object):
  def __init__(self):
    self.headers = {
      "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36",
      "Referer": "https://www.qiushibaike.com/"
    }
    # 实例化三个队列,用来存放内容
    self.url_queue = Queue()
    self.html_queue = Queue()
    self.content_queue = Queue()

  def get_total_url(self):
    """
    获取了所有的页面url,并且返回url_list
    return:url_list
    现在放入url_queue队列中保存
    """
    url_temp = "https://www.qiushibaike.com/text/page/{}/"
    url_list = list()
    for i in range(1,13):
      # url_list.append(url_temp.format(i))
      # 将生成的url放入url_queue队列
      self.url_queue.put(url_temp.format(i))

  def parse_url(self):
    """
    发送请求,获取响应,同时etree处理html
    """
    while self.url_queue.not_empty:
      # 判断非空,为空时结束循环

      # 从队列中取出一个url
      url = self.url_queue.get()
      print("parsing url:",url)
      # 发送请求
      response = requests.get(url,headers=self.headers,timeout=10)
      # 获取html字符串
      html = response.content.decode()
      # 获取element类型的html
      html = etree.HTML(html)
      # 将生成的element对象放入html_queue队列
      self.html_queue.put(html)
      # Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
      self.url_queue.task_done()

  def get_content(self):
    """
    解析网页内容,获取想要的信息
    """
    while self.html_queue.not_empty:
      items = list()
      html = self.html_queue.get()
      total_div = html.xpath("//div[@class='col1 old-style-col1']/div")
      for i in total_div:

        author_img = i.xpath(".//a[@rel='nofollow']/img/@src")
        author_img = "https"+author_img[0] if len(author_img)>0 else None

        author_name = i.xpath(".//a[@rel='nofollow']/img/@alt")
        author_name = author_name[0] if len(author_name)>0 else None

        author_href = i.xpath("./a/@href")
        author_href = "https://www.qiushibaike.com/"+author_href[0] if len(author_href)>0 else None

        author_gender = i.xpath("./div[1]/div/@class")
        author_gender = author_gender[0].split(" ")[-1].replace("Icon","").strip() if len(author_gender)>0 else None

        author_age = i.xpath("./div[1]/div/text()")
        author_age = author_age[0] if len(author_age)>0 else None

        content = i.xpath("./a/div/span/text()")
        content = content[0].strip() if len(content)>0 else None

        content_vote = i.xpath("./div[@class='stats']/span[@class='stats-vote']/i/text()")
        content_vote = content_vote[0] if len(content_vote)>0 else None

        content_comment_numbers = i.xpath("./div[@class='stats']/span[@class='stats-comments']/a/i/text()")
        content_comment_numbers = content_comment_numbers[0] if len(content_comment_numbers)>0 else None

        item = {
          "author_name":author_name,
          "author_age" :author_age,
          "author_gender":author_gender,
          "author_img":author_img,
          "author_href":author_href,
          "content":content,
          "content_vote":content_vote,
          "content_comment_numbers":content_comment_numbers,
        }
        items.append(item)
      self.content_queue.put(items)
      # task_done的时候,队列计数减一
      self.html_queue.task_done()

  def save_items(self):
    """
    保存items
    """
    while self.content_queue.not_empty:
      items = self.content_queue.get()
      with open("quishibaike.txt",'a',encoding='utf-8') as f:
        for i in items:
          json.dump(i,f,ensure_ascii=False,indent=2)
      self.content_queue.task_done()

  def run(self):
    # 获取url list
    thread_list = list()
    thread_url = threading.Thread(target=self.get_total_url)
    thread_list.append(thread_url)

    # 发送网络请求
    for i in range(10):
      thread_parse = threading.Thread(target=self.parse_url)
      thread_list.append(thread_parse)

    # 提取数据
    thread_get_content = threading.Thread(target=self.get_content)
    thread_list.append(thread_get_content)

    # 保存
    thread_save = threading.Thread(target=self.save_items)
    thread_list.append(thread_save)


    for t in thread_list:
      # 为每个进程设置为后台进程,效果是主进程退出子进程也会退出
      t.setDaemon(True)
      t.start()
    
    # 让主线程等待,所有的队列为空的时候才能退出
    self.url_queue.join()
    self.html_queue.join()
    self.content_queue.join()


if __name__=="__main__":
  obj = Qsbk()
  obj.run()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python3使用SMTP发送带附件邮件
Jun 16 Python
python 处理数字,把大于上限的数字置零实现方法
Jan 28 Python
Python跳出多重循环的方法示例
Jul 03 Python
Python Web框架之Django框架Model基础详解
Aug 16 Python
python线程中的同步问题及解决方法
Aug 29 Python
Python上下文管理器全实例详解
Nov 12 Python
pytorch 指定gpu训练与多gpu并行训练示例
Dec 31 Python
Python基于类路径字符串获取静态属性
Mar 12 Python
python同时遍历两个list用法说明
May 02 Python
Python接口测试数据库封装实现原理
May 09 Python
PyQt5 显示超清高分辨率图片的方法
Apr 11 Python
pytorch查看网络参数显存占用量等操作
May 12 Python
python的Jenkins接口调用方式
May 12 #Python
jenkins+python自动化测试持续集成教程
May 12 #Python
python百行代码自制电脑端网速悬浮窗的实现
May 12 #Python
基于Python的Jenkins的二次开发操作
May 12 #Python
Python-jenkins模块获取jobs的执行状态操作
May 12 #Python
Python-jenkins 获取job构建信息方式
May 12 #Python
python进行参数传递的方法
May 12 #Python
You might like
PHP通过正则表达式下载图片到本地的实现代码
2011/09/19 PHP
解决php接收shell返回的结果中文乱码问题
2014/01/23 PHP
PHP Echo字符串的连接格式
2016/03/07 PHP
PHP实现防盗链的方法分析
2017/07/25 PHP
JavaScript 编程引入命名空间的方法
2007/06/29 Javascript
JSON 教程 json入门学习笔记
2020/09/22 Javascript
Node.js实战 建立简单的Web服务器
2012/03/08 Javascript
表格单元格交错着色实现思路及代码
2013/04/01 Javascript
jQuery将多条数据插入模态框的示例代码
2014/09/25 Javascript
Javascript基础教程之数据类型 (数值 Number)
2015/01/18 Javascript
JS实现黑客帝国文字下落效果
2015/09/01 Javascript
常用javascript表单验证汇总
2020/07/20 Javascript
基于JavaScript代码实现自动生成表格
2016/06/15 Javascript
ajax前台后台跨域请求处理方式
2018/02/08 Javascript
js尾调用优化的实现
2019/05/23 Javascript
JAVA面试题 static关键字详解
2019/07/16 Javascript
快速解决layui弹窗按enter键不停弹窗的问题
2019/09/18 Javascript
解决Layui中templet中a的onclick参数传递的问题
2019/09/20 Javascript
NodeJS配置CORS实现过程详解
2020/12/02 NodeJs
原生微信小程序开发中 redux 的使用详解
2021/02/18 Javascript
python list使用示例 list中找连续的数字
2014/01/27 Python
Python机器学习之SVM支持向量机
2017/12/27 Python
python实现超简单的视频对象提取功能
2018/06/04 Python
用Python读取几十万行文本数据
2018/12/24 Python
python常用函数与用法示例
2019/07/02 Python
python中sklearn的pipeline模块实例详解
2020/05/21 Python
Python web如何在IIS发布应用过程解析
2020/05/27 Python
python asyncio 协程库的使用
2021/01/21 Python
blueseventy官网:铁人三项和比赛泳衣
2021/02/06 全球购物
解释一下钝化(Swap out)
2016/12/26 面试题
企业晚会策划方案
2014/05/29 职场文书
批评与自我批评总结
2014/10/17 职场文书
《爱的教育》读书心得
2014/11/08 职场文书
汉语拼音教学反思
2016/02/22 职场文书
重温经典:乔布斯在斯坦福大学的毕业演讲(双语)
2019/08/26 职场文书
python实现双链表
2022/05/25 Python