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

说明:糗事百科段子的爬取,采用了队列和多线程的方式,其中关键点是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()

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

(0)

相关推荐

  • Python3多线程爬虫实例讲解代码

    多线程概述 多线程使得程序内部可以分出多个线程来做多件事情,充分利用CPU空闲时间,提升处理效率.python提供了两个模块来实现多线程thread 和threading ,thread 有一些缺点,在threading 得到了弥补.并且在Python3中废弃了thread模块,保留了更强大的threading模块. 使用场景 在python的原始解释器CPython中存在着GIL(Global Interpreter Lock,全局解释器锁),因此在解释执行python代码时,会产生互斥锁来限

  • Python之多线程爬虫抓取网页图片的示例代码

    目标 嗯,我们知道搜索或浏览网站时会有很多精美.漂亮的图片. 我们下载的时候,得鼠标一个个下载,而且还翻页. 那么,有没有一种方法,可以使用非人工方式自动识别并下载图片.美美哒. 那么请使用python语言,构建一个抓取和下载网页图片的爬虫. 当然为了提高效率,我们同时采用多线程并行方式. 思路分析 Python有很多的第三方库,可以帮助我们实现各种各样的功能.问题在于,我们弄清楚我们需要什么: 1)http请求库,根据网站地址可以获取网页源代码.甚至可以下载图片写入磁盘. 2)解析网页源代码,

  • python爬虫中多线程的使用详解

    queue介绍 queue是python的标准库,俗称队列.可以直接import引用,在python2.x中,模块名为Queue.python3直接queue即可 在python中,多个线程之间的数据是共享的,多个线程进行数据交换的时候,不能够保证数据的安全性和一致性,所以当多个线程需要进行数据交换的时候,队列就出现了,队列可以完美解决线程间的数据交换,保证线程间数据的安全性和一致性. #多线程实战栗子(糗百) #用一个队列Queue对象, #先产生所有url,put进队列: #开启多线程,把q

  • 基python实现多线程网页爬虫

    一般来说,使用线程有两种模式, 一种是创建线程要执行的函数, 把这个函数传递进Thread对象里,让它来执行. 另一种是直接从Thread继承,创建一个新的class,把线程执行的代码放到这个新的class里. 实现多线程网页爬虫,采用了多线程和锁机制,实现了广度优先算法的网页爬虫. 先给大家简单介绍下我的实现思路: 对于一个网络爬虫,如果要按广度遍历的方式下载,它是这样的: 1.从给定的入口网址把第一个网页下载下来 2.从第一个网页中提取出所有新的网页地址,放入下载列表中 3.按下载列表中的地

  • 使用Python多线程爬虫爬取电影天堂资源

    最近花些时间学习了一下Python,并写了一个多线程的爬虫程序来获取电影天堂上资源的迅雷下载地址,代码已经上传到GitHub上了,需要的同学可以自行下载.刚开始学习python希望可以获得宝贵的意见. 先来简单介绍一下,网络爬虫的基本实现原理吧.一个爬虫首先要给它一个起点,所以需要精心选取一些URL作为起点,然后我们的爬虫从这些起点出发,抓取并解析所抓取到的页面,将所需要的信息提取出来,同时获得的新的URL插入到队列中作为下一次爬取的起点.这样不断地循环,一直到获得你想得到的所有的信息爬虫的任务

  • python面向对象多线程爬虫爬取搜狐页面的实例代码

    首先我们需要几个包:requests, lxml, bs4, pymongo, redis 1. 创建爬虫对象,具有的几个行为:抓取页面,解析页面,抽取页面,储存页面 class Spider(object): def __init__(self): # 状态(是否工作) self.status = SpiderStatus.IDLE # 抓取页面 def fetch(self, current_url): pass # 解析页面 def parse(self, html_page): pass

  • Python 微信爬虫完整实例【单线程与多线程】

    本文实例讲述了Python 实现的微信爬虫.分享给大家供大家参考,具体如下: 单线程版: import urllib.request import urllib.parse import urllib.error import re,time headers = ("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3107.

  • python爬虫爬取快手视频多线程下载功能

    环境: python 2.7 + win10 工具:fiddler postman 安卓模拟器 首先,打开fiddler,fiddler作为http/https 抓包神器,这里就不多介绍. 配置允许https 配置允许远程连接 也就是打开http代理 电脑ip: 192.168.1.110 然后 确保手机和电脑是在一个局域网下,可以通信.由于我这边没有安卓手机,就用了安卓模拟器代替,效果一样的. 打开手机浏览器,输入192.168.1.110:8888   也就是设置的代理地址,安装证书之后才能

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

    说明:糗事百科段子的爬取,采用了队列和多线程的方式,其中关键点是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": &q

  • Python并发编程队列与多线程最快发送http请求方式

    目录 队列+多线程 线程池 协程 + aiohttp grequests 最后的话 Python 并发编程有很多方法,多线程的标准库 threading,concurrency,协程 asyncio,当然还有 grequests 这种异步库,每一个都可以实现上述需求,下面一一用代码实现一下,本文的代码可以直接运行,给你以后的并发编程作为参考: 队列+多线程 定义一个大小为 400 的队列,然后开启 200 个线程,每个线程都是不断的从队列中获取 url 并访问. 主线程读取文件中的 url 放入

  • Python基础进阶之海量表情包多线程爬虫功能的实现

    一.前言 在我们日常聊天的过程中会使用大量的表情包,那么如何去获取表情包资源呢?今天老师带领大家使用python中的爬虫去一键下载海量表情包资源 二.知识点 requests网络库 bs4选择器 文件操作 多线程 三.所用到得库 import os import requests from bs4 import BeautifulSoup 四. 功能 # 多线程程序需要用到的一些包 # 队列 from queue import Queue from threading import Thread

  • python队列基本操作和多线程队列

    目录 一.队列基本操作 二.多线程队列 一.队列基本操作 from queue import Queue q = Queue(5)  # 创建一个容量为5的队列.如果给一个小于0的数,则队列为无限大小.(这是官方的解释,实际不是无限大小,而是跟内存有关) # 存储数据 q.put(123)  # 数值  q.put('hello world!')  # 字符串 q.put(['hello', 'world'])  # 列表 q.put(('hello', 'world'))  # 元组 q.pu

  • python实现爬虫统计学校BBS男女比例之多线程爬虫(二)

    接着第一篇继续学习. 一.数据分类 正确数据:id.性别.活动时间三者都有 放在这个文件里file1 = 'ruisi\\correct%s-%s.txt' % (startNum, endNum) 数据格式为293001 男 2015-5-1 19:17 没有时间:有id.有性别,无活动时间 放这个文件里file2 = 'ruisi\\errTime%s-%s.txt' % (startNum, endNum) 数据格式为2566 女 notime 用户不存在:该id没有对应的用户 放这个文件

  • php与python实现的线程池多线程爬虫功能示例

    本文实例讲述了php与python实现的线程池多线程爬虫功能.分享给大家供大家参考,具体如下: 多线程爬虫可以用于抓取内容了这个可以提升性能了,这里我们来看php与python 线程池多线程爬虫的例子,代码如下: php例子 <?php class Connect extends Worker //worker模式 { public function __construct() { } public function getConnection() { if (!self::$ch) { sel

  • Python多线程爬虫实战_爬取糗事百科段子的实例

    多线程爬虫:即程序中的某些程序段并行执行, 合理地设置多线程,可以让爬虫效率更高 糗事百科段子普通爬虫和多线程爬虫 分析该网址链接得出: https://www.qiushibaike.com/8hr/page/页码/ 多线程爬虫也就和JAVA的多线程差不多,直接上代码 ''' #此处代码为普通爬虫 import urllib.request import urllib.error import re headers = ("User-Agent","Mozilla/5.0

随机推荐