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 相关文章推荐
Python获取Linux系统下的本机IP地址代码分享
Nov 07 Python
Python 类与元类的深度挖掘 I【经验】
May 06 Python
Python使用zip合并相邻列表项的方法示例
Mar 17 Python
Python实现字典(dict)的迭代操作示例
Jun 05 Python
详解python之协程gevent模块
Jun 14 Python
Python操作rabbitMQ的示例代码
Mar 19 Python
python实现名片管理系统项目
Apr 26 Python
Python语言进阶知识点总结
May 28 Python
Python数据分析模块pandas用法详解
Sep 04 Python
python二维键值数组生成转json的例子
Dec 06 Python
matlab、python中矩阵的互相导入导出方式
Jun 01 Python
解决Python安装cryptography报错问题
Sep 03 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
全国FM电台频率大全 - 29 青海省
2020/03/11 无线电
透析PHP的配置文件php.ini
2006/10/09 PHP
经典的PHPer为什么被认为是草根?
2007/04/02 PHP
php 学习资料零碎东西
2010/12/04 PHP
PHP+memcache实现消息队列案例分享
2014/05/21 PHP
PHP Warning: Module 'modulename' already loaded in问题解决办法
2015/03/16 PHP
PHP实现一个轻量级容器的方法
2019/01/28 PHP
Bootstrap jquery.twbsPagination.js动态页码分页实例代码
2017/02/20 Javascript
JS实现发送短信验证后按钮倒计时功能(防止刷新倒计时失效)
2017/07/07 Javascript
vue.js 实现图片本地预览 裁剪 压缩 上传功能
2018/03/01 Javascript
微信小程序页面间值传递的两种方法
2018/11/26 Javascript
JavaScript原型式继承实现方法
2019/11/06 Javascript
js实现鼠标点击页面弹出自定义文字效果
2019/12/24 Javascript
JS实现简易贪吃蛇游戏
2020/08/24 Javascript
JS运算符优先级与表达式示例详解
2020/09/04 Javascript
jquery实现图片放大镜效果
2020/12/23 jQuery
使用python开发vim插件及心得分享
2014/11/04 Python
使用Python设置tmpfs来加速项目的教程
2015/04/17 Python
python 如何快速找出两个电子表中数据的差异
2017/05/26 Python
Python Nose框架编写测试用例方法
2017/10/26 Python
Python实现的字典值比较功能示例
2018/01/08 Python
利用Python如何将数据写到CSV文件中
2018/06/05 Python
python实现蒙特卡罗方法教程
2019/01/28 Python
django框架事务处理小结【ORM 事务及raw sql,customize sql 事务处理】
2019/06/27 Python
Django 缓存配置Redis使用详解
2019/07/23 Python
Window版下在Jupyter中编写TensorFlow的环境搭建
2020/04/10 Python
PyTorch的torch.cat用法
2020/06/28 Python
Numpy(Pandas)删除全为零的列的方法
2020/09/11 Python
Python中免验证跳转到内容页的实例代码
2020/10/23 Python
NET程序员上机面试题
2015/05/23 面试题
EntityManager都有哪些方法
2013/11/01 面试题
法律专业推荐信范文
2013/11/29 职场文书
幼儿园元旦家长感言
2014/02/27 职场文书
无财产离婚协议书范本
2014/10/28 职场文书
2015年电教工作总结
2015/05/26 职场文书
python中的sys模块和os模块
2022/03/20 Python