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对url格式解析的方法
May 13 Python
Python面向对象基础入门之设置对象属性
Dec 11 Python
python @classmethod 的使用场合详解
Aug 23 Python
Python paramiko模块使用解析(实现ssh)
Aug 30 Python
解决Numpy中sum函数求和结果维度的问题
Dec 06 Python
Scrapy框架介绍之Puppeteer渲染的使用
Jun 19 Python
Python爬虫之爬取淘女郎照片示例详解
Jul 28 Python
Python为何不支持switch语句原理详解
Oct 21 Python
python用tkinter实现一个gui的翻译工具
Oct 26 Python
基于PyInstaller各参数的含义说明
Mar 04 Python
Python-typing: 类型标注与支持 Any类型详解
May 10 Python
python 标准库原理与用法详解之os.path篇
Oct 24 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
dhtmlxTree目录树增加右键菜单以及拖拽排序的实现方法
2013/04/26 PHP
php连接mysql数据库
2017/03/21 PHP
thinkPHP5实现数据库添加内容的方法
2017/10/25 PHP
PHP多维数组排序array详解
2017/11/21 PHP
php把文件设置为插件的技巧方法
2020/02/03 PHP
CSS+Table图文混排中实现文本自适应图片宽度(超简单+跨所有浏览器)
2009/02/14 Javascript
IE与FireFox的JavaScript兼容问题解决办法
2013/12/31 Javascript
JavaScript正则表达式的分组匹配详解
2016/02/13 Javascript
jquery实现页面常用的返回顶部效果
2016/03/04 Javascript
js从外部获取图片的实现方法
2016/08/05 Javascript
JS之获取样式的简单实现方法(推荐)
2016/09/13 Javascript
vue-router配合ElementUI实现导航的实例
2018/02/11 Javascript
微信小程序实现发红包功能
2018/07/11 Javascript
使用JavaScript实现node.js中的path.join方法
2018/08/12 Javascript
解决vue 引入子组件报错的问题
2018/09/06 Javascript
JavaScript页面倒计时功能完整示例
2019/05/15 Javascript
JavaScript生成随机验证码代码实例
2019/09/28 Javascript
JavaScript实现点击切换验证码及校验
2021/01/10 Javascript
在Django的上下文中设置变量的方法
2015/07/20 Python
Python+Selenium+PIL+Tesseract自动识别验证码进行一键登录
2017/09/20 Python
python使用pil进行图像处理(等比例压缩、裁剪)实例代码
2017/12/11 Python
Django项目使用ckeditor详解(不使用admin)
2019/12/17 Python
python GUI库图形界面开发之PyQt5日期时间控件QDateTimeEdit详细使用方法与实例
2020/02/27 Python
Keras:Unet网络实现多类语义分割方式
2020/06/11 Python
CSS3实现背景透明文字不透明的示例代码
2018/06/25 HTML / CSS
Html5 video标签视频的最佳实践
2020/02/26 HTML / CSS
马来西亚领先的在线礼品店:Giftr
2018/08/23 全球购物
荷兰最大的儿童服装店:The Kids Republic
2019/04/13 全球购物
Arti-shopping中文官网:大型海外商品一站式直邮平台
2020/03/23 全球购物
副主任竞聘演讲稿
2014/08/18 职场文书
2015年七七事变78周年纪念活动方案
2015/05/06 职场文书
员工升职自我评价
2019/03/26 职场文书
python实现局部图像放大
2021/11/17 Python
通过T-SQL语句创建游标与实现数据库加解密功能
2022/03/16 SQL Server
《游戏王:大师决斗》新活动上线 若无符合卡组可免费租用
2022/04/13 其他游戏
关于pytest结合csv模块实现csv格式的数据驱动问题
2022/05/30 Python