9.异步爬虫

news2024/11/15 13:28:30

异步爬虫可以理解为非只单线程爬虫

我们下面做个例子,之前我们通过单线程爬取过梨视频 https://blog.csdn.net/potato123232/article/details/135672504

在保存视频的时候会慢一些,为了提升效率,我们使用异步爬虫爬取

目录

1  线程池

2  单线程+异步协程

2.1  aiohttp的基本使用

2.2  爬取梨视频

3  单线程,协程,多线程的运行速度比较


1  线程池

线程池的基本用法在这里有提到 python并发任务-CSDN博客

多线程应仅用于耗时的部分,如果我们为了省事去将所有部分都封装为一个函数就容易出错

  • 走单线程可以成功爬取10个视频,当我将所有过程封装为一个函数时,使用多线程爬取会报错。在JS中的异步也会有这种问题,就像是请求还没请求完,后面加载就加载上了
import requests
from lxml import etree
import random
import re
from multiprocessing.dummy import Pool

# 保存根页面
url = 'https://www.pearvideo.com/popular'
headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36'}
response = requests.get(url=url,headers=headers)
response.encoding = response.apparent_encoding
with open('./test.html','w',encoding='utf-8') as f:
    f.write(response.text)
print(response)

# 获取所有细节页面url
detail_htmls = []
tree = etree.HTML(response.text)
for i in range(1,len(tree.xpath('//*[@id="popularList"]/li'))+1):
    detail_htmls.append({'url':'https://www.pearvideo.com/' + tree.xpath('//*[@id="popularList"]/li[{}]/a/@href'.format(i))[0],'title':tree.xpath('//*[@id="popularList"]/li['+ str(i) +']/div[2]/a/h2/text()')[0]})

# print(detail_htmls)
p = re.compile(r'.*\/(.*?)-\d')

video_detail_list = []
for i in detail_htmls:
    contId = i['url'].split('_')[-1]
    mrd = round(random.random(), 16)
    headers['Host'] = 'www.pearvideo.com'
    headers['Referer'] = i['url']
    response = requests.get(url='https://www.pearvideo.com/videoStatus.jsp?contId=' + str(contId) + '&mrd=' + str(mrd),
                            headers=headers).text

    srcUrl = eval(response).get('videoInfo').get('videos').get('srcUrl')

    need_change_part = p.findall(srcUrl)[0]
    true_video_url = srcUrl.split(need_change_part)[0] + 'cont-' + contId + srcUrl.split(need_change_part)[1]

    video_name = re.sub(r'[\\/:*?"<>|]', '', i['title'])
    video_detail_list.append({"name":video_name,"url":true_video_url})

print(video_detail_list)
def get_video(item):
    response = requests.get(item['url'])
    with open('./result/' + str(item['name']) + '.mp4', 'wb') as fp:
        fp.write(response.content)
        print(item['url'] + '下载成功')

pool = Pool(4)
pool.map(get_video,video_detail_list)

耗时的部分只有保存,所以我们保存的部分剥离出来,这样就能成功爬取10个视频

2  单线程+异步协程

2.1  aiohttp的基本使用

我们先做个简单的服务,这三个服务无论请求哪一个都会等待两秒,然后返回一个字符串

之后我们尝试只用asyncio发起异步请求

从耗时来看这段代码并没有发起异步请求

这个时候我们可以使用aiohttp进行异步请求

  • 这个能看懂就行了,如果到了一定要使用的时候,看看别人怎么写的抄一抄就完了
  • 如果不加最后打印之前的await,那么就有可能会打印不出来东西,由于请求是异步的,他会跳过请求而执行下面,就像js中的定时器
  • response.text()是返回字符串类型的响应,read()是返回二进制类型的响应,json()返回的是json对象类型的响应
  • 除了发get请求还可以发post请求,参数与requests.get(),requests.post()基本一致(get用的params一致,post用的data一致,请求头headers一致,aiohttp的代理参数名为proxy,proxy参数值为字符串)

2.2  爬取梨视频

异步保存文件可以借助 aiofiles

import requests
from lxml import etree
import random
import re
import aiohttp
import asyncio
import aiofiles

# 保存根页面
url = 'https://www.pearvideo.com/popular'
headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36'}
response = requests.get(url=url,headers=headers)
response.encoding = response.apparent_encoding
with open('./test.html','w',encoding='utf-8') as f:
    f.write(response.text)
print(response)

# 获取所有细节页面url
detail_htmls = []
tree = etree.HTML(response.text)
for i in range(1,len(tree.xpath('//*[@id="popularList"]/li'))+1):
    detail_htmls.append({'url':'https://www.pearvideo.com/' + tree.xpath('//*[@id="popularList"]/li[{}]/a/@href'.format(i))[0],'title':tree.xpath('//*[@id="popularList"]/li['+ str(i) +']/div[2]/a/h2/text()')[0]})

# print(detail_htmls)
p = re.compile(r'.*\/(.*?)-\d')

video_detail_list = []
for i in detail_htmls:
    contId = i['url'].split('_')[-1]
    mrd = round(random.random(), 16)
    headers['Host'] = 'www.pearvideo.com'
    headers['Referer'] = i['url']
    response = requests.get(url='https://www.pearvideo.com/videoStatus.jsp?contId=' + str(contId) + '&mrd=' + str(mrd),
                            headers=headers).text

    srcUrl = eval(response).get('videoInfo').get('videos').get('srcUrl')

    need_change_part = p.findall(srcUrl)[0]
    true_video_url = srcUrl.split(need_change_part)[0] + 'cont-' + contId + srcUrl.split(need_change_part)[1]

    video_name = re.sub(r'[\\/:*?"<>|]', '', i['title'])
    video_detail_list.append({"name":video_name,"url":true_video_url})

print(video_detail_list)

async def test(item):
    async with aiohttp.ClientSession() as session:
        async with await session.get(item['url']) as response:
            async with aiofiles.open('./result/' + str(item['name']) + '.mp4', 'wb') as fp:
                await fp.write(await response.read())
                print(item['url'] + '下载成功')

future_list = []
for something1 in video_detail_list:
    a = test(something1)
    future = asyncio.ensure_future(a)
    future_list.append(future)

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(future_list))

可以爬取成功,每个视频都可以点开看

但是代码在pycharm的返回值并不是0

3  单线程,协程,多线程的运行速度比较

就梨视频的例子来说,单线程最慢,多线程第二(因为我只用4线程,如果10线程应该还会快一些),感觉上来讲协程最快

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1414642.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Numpy应用-股价分析实战

股价统计分析 数据样本 股价常用指标 极差 越高说明波动越明显 股价近期最高价的最大值和最小值的差价 成交量加权平均价格 英文名VWAP&#xff08;Volume-Weighted Average Price&#xff0c;成交量加权平均价格&#xff09;是一个非常重要的经济学量&#xff0c;代表着金融…

vcruntime140.dll丢失问题全面分析,解决vcruntime140.dll丢失的办法

当vcruntime140.dll文件缺失时&#xff0c;系统会显示错误信息来提示用户。这些错误信息可能会包含类似于"vcruntime140.dll未找到"或"找不到vcruntime140.dll"等字样。通常出现这样的字样那就是导致应用程序通常无法正常启动或执行相关功能。那么出现这样…

【排序4】探秘归并排序:提高程序效率的必备技巧

&#x1f60a;归并排序 &#x1f38a;1、基本思想&#x1f38a;2、代码示例&#x1f38a;3、非递归实现&#x1f38a;4、归并排序的性能分析&#x1f38a;5、归并排序的优缺点&#x1f38a;6、归并排序的应用场景&#x1f38a;7、总结 &#x1f38a;1、基本思想 归并排序&…

ssh异常报错:Did not receive identification string from

一、问题描述 某次外出在异地工作场所xshell炼乳远程服务器时&#xff0c;报错&#xff1a;Connection closed by foreign host. D&#xff0c;服务器查看secure日志或sshd服务状态会显示&#xff1a;id not receive identification string from client_ip; 二、分析处理 1&a…

J9数字论:什么是公链、联盟链、私有链?它们之间区别在哪?

公有链是任何人都能参与读取、交易、写入的区块链&#xff0c;完全去中心化&#xff0c;账本信息公开透明&#xff0c;不受任何机构控制。公有链一般都需要挖矿来达成共识&#xff0c;因此带来了交易延时高、成本高和效率低等缺点。公有链的典型代表有比特币、以太坊、EOS等。私…

Vite学习指南

那本课程都适合哪些人群呢&#xff1f; 想要学习前端工程化&#xff0c;在新项目中投入使用 Vite 构建工具的朋友 Webpack 转战到 Vite 的小伙伴 前端架构师们&#xff0c;可以充实自己的工具箱 当然如果你没有项目相关开发经验&#xff0c;也可以从本课程中受益&#xff0…

你应该知道的GNU C语句表达式

许多写C语言的同道们或许都知道C语言中的表达式和语句&#xff0c;一般常见的语句都是在表达式后跟分号做结尾。例如&#xff0c; a 10 /*赋值表达式*/a 10; /*赋值语句*/当然语句不止有这一种&#xff0c;暂不过多引入。 我们都知道有些表达式是有其值的&#xff0c;例如上…

查询redis路径,清除redis缓存

查询redis路径 1、执行ps -ef | grep redis 命令&#xff0c;结果如下&#xff08;记住PID&#xff09; 2、执行ps -u 系统用户名&#xff0c;进一步确定进程id, 我这里的系统用户名是root&#xff0c;执行ps -u root&#xff0c;结果如下&#xff1a; 结合1的操作结果图可知…

taro3 + vue3 + ts 跨平台体验记录

taro3 vue3 ts 跨平台体验记录&#xff0c;根据进度不定期更新。 目标平台包含&#xff1a;H5、微信小程序、APP。开发环境&#xff1a;windows 安装cli【官方安装文档】 npm install -g tarojs/cli常用命令 // 查看taro版本 npm info tarojs/cli创建demo项目 taro init…

个体诊所电子处方系统设计,社区门诊处方开单管理系统软件教程

个体诊所电子处方系统设计&#xff0c;社区门诊处方开单管理系统软件教程 一、前言 以下软件程序操作教程以 佳易王诊所电子处方管理系统软件V17.3为例说明 如图&#xff0c;在基本信息设置里&#xff0c;可以设置处方配方模板&#xff0c;这样在开电子处方的时候可以一键导入…

C++中map和set的使用

&#xff08;图片来源于网络&#xff09; &#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;强烈推荐优质专栏: &#x1f354;&#x1f35f;&#x1f32f;C的世界(持续更新中) &#x1f43b;推荐专栏1: &#x1f354;&#x1f35f;&#x1f32f;C语言初阶…

插槽(64-67)

文章目录 插槽1.插槽 - 默认插槽(组件内可以定制一处结构)2.插槽 - 后备内容&#xff08;默认值&#xff09;3.插槽 - 具名插槽(组件内可以定制多处结构)4.作用域插槽(插槽的一个传参语法) 插槽 插槽分类:默认插槽和具名插槽 1.插槽 - 默认插槽(组件内可以定制一处结构) 作用…

JavaEE-微服务-Vuex

Vuex 2.1 什么是Vuex Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。 Vuex在组件之间共享数据。 2.2 使用 vue cli 构建项目 2.3 入门案例 2.3.1 定义数据 export default new Vuex.Store({state: { // 状态区域&#xff08;定义变量区域&#xff09;user: ,toke…

table用position: sticky固定多层表头,滑动滚动条border边框透明解决方法

问题&#xff1a;我们发现&#xff0c;只要设置了border边框&#xff0c;这个位置滑动有内容经过就会出现如图的情况。 解决的方法&#xff1a;用outline&#xff08;轮廓&#xff09;替代border,以达到我们想要的样式。 table thead tr {border: none;outline-color: #fff;ou…

[SWPUCTF 2018]SimplePHP1

打开环境 有查看文件跟上传文件&#xff0c;查看文件里面显示没有文件url貌似可以文件读取 上传文件里面可以上传文件。 先看一下可不可以文件读取 /etc/passwd不能读取&#xff0c;源码提示flag在f1ag.php 看看能不能读取当前的文件&#xff0c; 先把代码摘下来 file.php …

Ubuntu 22.04 apt 安装 ros1 ros Noetic Ninjemys

众所周知 ros2还有很多功能没有移植&#xff0c;而ros1官方不再支持 ubuntu 20.04 之后的版本。另一方面Ubuntu 22.04 更新了很多对新硬件的驱动&#xff0c;有更好的兼容性和体验&#xff0c;这就变的很纠结。 如果想在 22.04 使用最新版本的 ros noetic 只有自己编译一个办法…

盘古信息IMS OS 数垒制造操作系统+ 产品及生态部正式营运

启新址吉祥如意&#xff0c;登高楼再谱新篇。2024年1月22日&#xff0c;广东盘古信息科技股份有限公司新办公楼层正式投入使用并举行了揭牌仪式&#xff0c;以崭新的面貌、奋进的姿态开启全新篇章。 盘古信息总部位于东莞市南信产业园&#xff0c;现根据公司战略发展需求、赋能…

java金额数字转中文

java金额数字转中文 运行结果&#xff1a; 会进行金额的四舍五入。 工具类源代码&#xff1a; /*** 金额数字转为中文*/ public class NumberToCN {/*** 汉语中数字大写*/private static final String[] CN_UPPER_NUMBER {"零", "壹", "贰",…

机器学习第一个项目-----鸢尾花数据集加载及报错解决

项目步骤 如刚开始做&#xff0c;从 “项目开始” 看&#xff1b; 如遇到问题从 “问题” 开始看&#xff1b; 问题 报错如下 ModuleNotFoundError: No module named sklearn解决过程 查看官网&#xff0c;感觉可能是python版本和skilearn版本不匹配&#xff0c;更新一下p…

Django模型(一)

一、介绍 模型,就是python中的类对应数据库中的表 1.1、ORM ORM 就是通过实例对象的语法,完成关系型数据库的操作的技术,是"对象-关系映射"(Object/Relational Mapping) 的缩写 ORM 把数据库映射成对象 1.2、示例 1.2.1、模型 from django.db import models…