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实现批量下载新浪博客的方法
Jun 15 Python
python实现按任意键继续执行程序
Dec 30 Python
python编程线性回归代码示例
Dec 07 Python
使用python实现knn算法
Dec 20 Python
安装python3的时候就是输入python3死活没有反应的解决方法
Jan 24 Python
Django中Forms的使用代码解析
Feb 10 Python
python实现随机梯度下降法
Mar 24 Python
通过cmd进入python的实例操作
Jun 26 Python
Django实现web端tailf日志文件功能及实例详解
Jul 28 Python
Pycharm+Python工程,引用子模块的实现
Mar 09 Python
Django开发RESTful API实现增删改查(入门级)
May 10 Python
写好Python代码的几条重要技巧
May 21 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
Terran兵种介绍
2020/03/14 星际争霸
preg_match_all使用心得分享
2014/01/31 PHP
PHP实现自动登入google play下载app report的方法
2014/09/23 PHP
学习php开源项目的源码指南
2014/12/21 PHP
PHP多线程之内部多线程实例分析
2015/03/09 PHP
使用WordPress发送电子邮件的相关PHP函数用法解析
2015/12/15 PHP
Mac下快速搭建PHP开发环境步骤详解
2019/05/05 PHP
javaScript对象和属性的创建方法
2007/01/15 Javascript
PNG背景在不同浏览器下的应用
2009/06/22 Javascript
javascript中字符串的定义示例代码
2013/12/19 Javascript
深入理解JavaScript系列(29):设计模式之装饰者模式详解
2015/03/03 Javascript
js获取form的方法
2015/05/06 Javascript
JavaScript实现获取某个元素相邻兄弟节点的prev与next方法
2016/01/25 Javascript
移动端触摸滑动插件swiper使用方法详解
2017/08/11 Javascript
引入JavaScript时alert弹出框显示中文乱码问题
2017/09/16 Javascript
webpack4的迁移的使用方法
2018/05/25 Javascript
JS+Canvas实现五子棋游戏
2020/08/26 Javascript
OpenLayers3实现测量功能
2020/09/25 Javascript
vue组件中节流函数的失效的原因和解决方法
2020/12/02 Vue.js
[01:45]DOTA2新英雄“神谕者”全方位展示
2014/11/21 DOTA
Django中URL视图函数的一些高级概念介绍
2015/07/20 Python
深入理解Python对Json的解析
2017/02/14 Python
Python爬虫DOTA排行榜爬取实例(分享)
2017/06/13 Python
Python使用微信SDK实现的微信支付功能示例
2017/06/30 Python
详解Python核心编程中的浅拷贝与深拷贝
2018/01/07 Python
wxPython实现窗口用图片做背景
2018/04/25 Python
详解python中@的用法
2019/03/27 Python
pip指定python位置安装软件包的方法
2019/07/12 Python
pandas factorize实现将字符串特征转化为数字特征
2019/12/19 Python
Python selenium页面加载慢超时的解决方案
2020/03/18 Python
python实现读取类别频数数据画水平条形图案例
2020/04/24 Python
护士个人简历自荐信
2013/10/18 职场文书
企业管理毕业生求职信范文
2014/03/07 职场文书
邀请书格式范文
2015/02/02 职场文书
法律讲堂观后感
2015/06/11 职场文书
python关于集合的知识案例详解
2021/05/30 Python