并发下载~

并发下载

  • 了解多线程爬虫的流程
  • 掌握queue模块的使用,可以利用它实现多线程爬虫
  • 熟悉协程使用,能够用协程技术实现并发出爬虫

多线程爬虫流程分析

  1. 准备一个网址列表,是要爬取数据的网页列表
  2. 调试启动多个线程爬取网页内容
  3. 将爬取的网页源代码存储在一个列表中
  4. 同时使用多个线程对网页源代码表的网页内容进行解析
  5. 将解析之后的数据存储起来

使用queue模块实现多线程爬虫

多线程爬虫要在内存中存储数据,包括待爬取的网页列表、爬取到的数据等。

queue模块简介

queue模块是python内置的标准模块,可以直接通过 import queue 引用。

Queue

Queue类表示一个基本的FIFO(First In First Out)队列,创建方法是Queue.Queue(maxsize=0),其中maxsize是一个整数,指明了列队中能存放的数据个数的上限。

from queue import Queue
queue_object=Queue()
for i in range(4):
    queue_object.put(i)
while not queue_object.empty():
    print(queue_object.get())

LifoQueue

LifoQueue表示后进先出队列(Last in First out),与栈类似,创建方法也很简单,使用Queue.LifoQueue(maxsize=0),

from queue import LifoQueue
queue_object = LifoQueue()
for i in range(4):
    queue_object.put(i)
while not queue_object.empty():
    print(queue_object.get())

PriorityQueue

PriorityQueue表示优先级列队,按级别顺序取出元素,级别最低的最先取出。一般优先级列队中的元素采取元组的形式储存。

from queue import PriorityQueue


class Job(object):
    def _init_(self, level, description):
        self.level = level
        self.description = description
        return

    def __lt__(self, other):
        return self.level < other.level


priority_queue = PriorityQueue()
priority_queue.put(Job(5, '中级'))
priority_queue.put(Job(10, '低级'))
priority_queue.put(Job(1, '高级'))
while not priority_queue.empty():
    next_job = priority_queue.get()
    print('开始', next_job.description)

两个异常

  1. Empty:当从空列队中取数据是,可抛出该异常
  2. Full:当向一个满列队中存储数据时,可抛出此异常

Queue类概述

Queue提供了以下数据存储和管理的常用方法:

  • queue.Queue(maxsize) :用于创建列队
  • empty() :队列为空,返回True,否则返回False
  • full() :队列已满返回True,否则返回False
  • qsize() :返回队列大小
  • get(block=True,timeout=None) :从对头获取并删除第一个元素。
    1. block,默认为True,即当队列为空时,阻塞当前线程;反之不阻塞,而是抛出Empty异常。
    2. timeout:设置阻塞的最大时长
  • put(item,block=True,time=None) :在队尾添加一个元素,item为添加元素的值。
  • get_nowait() :立即取出一个元素,不等待
  • put_nowait() :立即放入一个元素,不等待
  • task_down() :在完成一项工作之后,task_down()函数向任务已完成的队列发送一个信号。
  • join() :阻塞当前线程,直到队列中所以元素都已经被处理。

协程实现并发爬取

协程:指同时开启多个任务,但一次只顺序执行一个。等所执行的任务遭遇阻塞,就切换到下一个任务继续执行,从而节省阻塞所用的时间。

协程爬虫的流程

  1. 准备一个待爬取的网址列表。
  2. 为每一个网址创建一个协程并启动该协程
  3. 将爬取到的目标存储在一个列表中
  4. 遍历数据列表,将数据存储在本地文件中

第三方库gevent

gevent的安装:

pip install gevent

常用方法:

  • gevent.spawn() :创建并启动协程
  • gevent.joinall() :等待所以协程执行完毕

爬取糗事百科里面的段子

# -*- coding = utf-8 -*-
# @Time :2021/7/4 9:41
# @Author : 黄小敏
# @File : singleThreading
# @Software : PyCharm
from lxml import etree
import requests
import json

# 访问网页的请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
                  ' AppleWebKit/537.36 (KHTML, like Gecko) Chrom'
                  '/91.0.4472.124 Safari/537.36'
}
# 存储解析后数据的本地文件
local_file = open('duanzi.json', 'a')


# 解析html字符串,获取需要的信息
def parse_html(html):
    text = etree.HTML(html)
    # 返回所有段子结点的位置
    # contains模糊查询,第一个参数时要匹配的标签,第二个参数是标签名的部分内容
    node_list = text.xpath('//div[contains(@id,"qiushi_tag")]')
    for node in node_list:
        try:
            username = node.xpath('./div')[0].xpath(".//h2")[0].text
            image = node.xpath('.//div[@class="thumb"]//@src')
            content = node.xpath('.//div[@class="content"]/span')[0].text
            like = node.xpath('.//i')[0].text
            comments = node.xpath('.//i')[1].text
            # 构建json格式的字符串
            items = {
                "username": username,
                "content": content,
                "image": image,
                "zan": like,
                "comments": comments
            }
            # 写入存储的解析后的数据
            local_file.write(json.dumps(items, ensure_ascii=False) + "\n")
        except:
            pass


def main():
    # 循环获取第1-20页共20页的网页源代码,并解析
    for page in range(1, 21):
        url = "https://www.qiushibaike.com/hot/page/" + str(page) + "/"
        html = requests.get(url, headers=headers).text
        parse_html(html)

if __name__ == '__main__':
    main()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值