当前位置: 首页 > 编程日记 > 正文

Python 多进程、协程异步抓取英雄联盟皮肤并保存在本地

00f6b5d4e1ba625a925ff32e20855687.gif

作者 | 俊欣

来源 | 关于数据分析与可视化

就在11月7日晚间,《英雄联盟》S11赛季全球总决赛决斗,在冰岛拉开“帷幕”,同时面向全球直播。在经过了5个小时的鏖战,EDG战队最终以3:2战胜来自韩国LCK赛区的DK战队,获得俱乐部队史上首座全球总决赛冠军。

cd59834884963309de7cc35471d0d6bd.png

夺冠的消息瞬间引爆全网,包括小编的朋友圈也被刷屏了,今天小编就写一篇与之相关的文章,通过单线程多进程以及异步协程等方法来抓取英雄联盟的皮肤并下载。

传统数据抓取 VS 高性能数据抓取

传统的数据抓取都是运行在单线程上的,先用获取到目标页面中最大的页数,然后循环抓取每个单页数据并进行解析,按照这样的思路,会有大量的时间都浪费在等待请求传回的数据上面,如果在等待第一个页面返回的数据时去请求第二个页面,就能有效地提高效率,下面我们就通过单线程多进程以及异步协程的方式分别来简单的实践一下。

页面分析

目标网站:https://lol.qq.com/data/info-heros.shtml

c462e08553509f520a5dd7fc8befb56a.png

官网的界面如图所示,上面的每一张小图代表每一个英雄,我们知道每一个英雄有多个皮肤,我们的目标就是爬取每一个英雄的所有皮肤,并且保存在本地

打开一个英雄显示他所有的皮肤,如下图所示,

41b748fb3face29f5f371da5ec035c49.png

我们打开浏览器里面的开发者工具,查看皮肤数据的接口,

1bee4abb6853bb89398acc087327ef4f.png

可以看到皮肤的信息是通过json的数据格式来进行传输的,并且存放皮肤的url也是有一定规律的,和英雄的ID相挂钩

url1 = 'https://game.gtimg.cn/images/lol/act/img/js/hero/1.js' 
url2 = 'https://game.gtimg.cn/images/lol/act/img/js/hero/2.js' 
url3 = 'https://game.gtimg.cn/images/lol/act/img/js/hero/3.js'
url4 = 'https://game.gtimg.cn/images/lol/act/img/js/hero/4.js'

因此我们也可以自己来构造这个url格式

'https://game.gtimg.cn/images/lol/act/img/js/hero/{}.js'.format(i)

单线程方案

我们先来看一下单线程的方案

def get_page():page_urls = []for i in range(1, 10):url = 'https://game.gtimg.cn/images/lol/act/img/js/hero/{}.js'.format(i)page_urls.append(url)return page_urls# 获取各英雄皮肤的链接
def get_img_urls():results_list = []page_urls = get_page()for page_url in page_urls:res = requests.get(page_url, headers=headers)result = res.content.decode('utf-8')result_dict = json.loads(result)skins_list = result_dict["skins"]for skin in skins_list:hero_dict = {}hero_dict['name'] = skin["heroName"]hero_dict['skin_name'] = skin["name"]if skin["mainImg"] == '':continuehero_dict['imgUrl'] = skin["mainImg"]results_list.append(hero_dict)time.sleep(2)return results_list# 将各种皮肤保存到本地
def save_image(index, img_url):path = "skin/" + img_url["name"]if not os.path.exists(path):os.makedirs(path)response = requests.get(img_url['imgUrl'], headers = headers).contentwith open('./skin/' + img_url['name'] + '/' + img_url['skin_name'] + str(index) + '.jpg', 'wb') as f:f.write(response)

上面的代码分别代表的获取各英雄每个皮肤的链接,然后再将各英雄的皮肤图片保存到本地,通过一个主函数将上面的步骤都串联到一起

def main():img_urls = get_img_urls()print("总共有{}个网页".format(len(img_urls)))for index, img_url in enumerate(img_urls):print("目前正处于第{}个".format(img_urls.index(img_url)))save_image(index, img_url)print("Done")

爬取这几个网页然后保存到本地的时间总共是需要43秒的时间,接下来我们来看一下多进程的爬取所需要的时间。

多进程的抓取方案

首先来简单的介绍一下进程,进程是系统进行资源分配和调度的最小单位,每一个进程都有自己独立的地址空间,不同进程之间的内存空间不共享,进程与进程之间的通信是由操作系统来传递的,因此通讯效率低,切换开销大。

这里我们简单的用多进程来抓取一下各个英雄的皮肤

def main():img_urls = get_img_urls()print("总共有{}个网页".format(len(img_urls)))pools = multiprocessing.Pool(len(img_urls))for index_1, img_url in enumerate(img_urls):print("目前正处于第{}个".format(img_urls.index(img_url)))pools.apply_async(save_image, args=(index_1, img_url, ))pools.close() # 关闭进程池(pool),使其不在接受新的任务。pools.join() # 主进程阻塞等待子进程的退出, join方法要在close或terminate之后使用print("Done")

整体下来需要的时间是29秒,比上面的单线程要快出许多。

异步协程的抓取方案

与异步相对立的则是同步,顾名思义,同步具体指的各个任务并不是独立进行的,而是按照顺序交替进行下去的,在一个任务进行完之后得到结果才进行下一个的任务。

而异步则是各个任务可以独立的运行,一个任务的运行不受另外一个任务的影响。而这里提到的协程,英文叫做Coroutine,也称为是微线程,是一种用户态的轻量级线程,拥有自己的寄存器上下文和栈,在进行调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候恢复先前保存的寄存器上下文和栈。

4cd1911494f5446e6032900fd116fec2.png

我们可以利用协程来实现异步操作,比如在发出请求的时候,需要等一段时间才能得到返回的结果,但其实这个等待的时候程序完全可以干其他许多的事情,在响应返回之后再切换回来继续处理,这样可以充分利用 CPU 和其他资源。

我们这里用协程来抓取一下各个英雄的皮肤

async def save_image(index, img_url):path = "skin/" + img_url["name"]if not os.path.exists(path):os.makedirs(path)response = requests.get(img_url['imgUrl'], headers = headers).contentwith open('./skin/' + img_url['name'] + '/' + img_url['skin_name'] + str(index) + '.jpg', 'wb') as f:f.write(response)def main():loop = asyncio.get_event_loop()img_urls = get_img_urls()print("总共有{}个网页".format(len(img_urls)))tasks_list = [save_image(index, img_url) for index, img_url in enumerate(img_urls)]try:loop.run_until_complete(asyncio.wait(tasks_list))finally:loop.close()print("Done")

一整个跑下来,大概是需要33秒的时间,也是比单线程的43秒要快出很多

以上便是用单线程、多进程以及异步协程的方式来优化爬虫脚本的性能,感兴趣的读者可以自己照着上面的教程与步骤自己去敲一遍代码,感谢阅读。

a7328bb03f7ead5ae8ce808e306bde2a.png

资讯

GPT-3与小学生的做题之战……

技术

如何利用python爬取高清精美壁纸

技术

Pandas生成炫酷的动态交互时图表

福利

赠书|深度学习视频理解之图像分类

94bda5d554464f87751463594c2eaa80.png

分享

9c825ce481791ef63a91e5da368d6740.png

点收藏

526c966b8d6b705cc8f43bc39b10f8e1.png

点点赞

4f8075f538e40671377b2d6664e7a1ad.png

点在看

相关文章:

QT 5.4.1 for Android Ubuntu QtWebView Demo

QT 5.4.1 for Android Ubuntu QtWebView Demo 2015-5-15 目录 一、说明: 二、参考文章: 三、QtWebView Demo在哪里? 四、Qt Creator 3.4.0能打开QtWebView Demo? 五、Qt Creator如何生成AndroidManifest.xml? 一、…

硬改TP-Link WR841N v8刷breed和OpenWrt

找到了以前的路由器,想刷OpenWrt但版本是TP-Link的WR841N v8版,上网查过才知道,是专门面向国内发布的严重缩水版国际版的Flash是4M,内存RAM是32M,国内版是2M/16M,不过论坛上也有人说到手的Flash是4M的。(Op…

Facebook的实时Hadoop系统

原文地址: http://blog.solrex.org/articles/facebook-realtime-hadoop-system.html作者:杨文博Facebook 在今年六月 SIGMOD 2011 上发表了一篇名为“Apache Hadoop Goes Realtime at Facebook”的会议论文 (pdf),介绍了 Facebook 为了打造一…

Ka的回溯编程练习 Part1|整划什么的。。

1 #include<stdio.h>2 int search(int s,int t);3 void op(int k);4 int res[1001]{1},n;5 int main()6 {7 //scanf("%d",&n);8 n10;9 search(n,1); 10 return 0; 11 } 12 int search(int s,int t) //当前数的大小s&#xff0c;个数n 13 …

开发者关心的十个数据库技术问题

作者 | 雷海林 责编 | 田玮靖出品 | 《新程序员》如今&#xff0c;数据库越来越受到业界的广泛关注&#xff0c;许多高校毕业生及资深技术人也逐渐投身于数据库产业。《新程序员002》经过用户、专家调研&#xff0c;收集汇总了十个开发者关心的数据库技术问题&#xff0c…

使用T-SQL语句操作数据表-更新数据

使用update语句更新表中的数据。也就是修改表中的数据。update语法格式&#xff1a;update <表名> set <列名更新值> [where <更新条件>] 解释&#xff1a;update 是更新数据名&#xff0c; 表明是更新数据set 是必要的&#xff0c; 后面可以紧随多个数据列的…

Category Archives: Linux

原文地址&#xff1a;http://blog.solrex.org/articles/solrex-linux-cheatsheet.html Cheatsheet&#xff1a;原意是考试的时候带的小抄&#xff0c;所以说是 cheat&#xff08;作弊&#xff09; sheet。在计算机科学领域里&#xff0c;主要是指记录一些难记命令或者操作的快查…

利用 OpenCV+ConvNets 检测几何图形

作者 | 小白 来源 | 小白学视觉 导读 人工智能领域中增长最快的子领域之一是自然语言处理&#xff08;NLP&#xff09;&#xff0c;它处理计算机与人类&#xff08;自然&#xff09;语言之间的交互&#xff0c;特别是如何编程计算机以处理和理解大量自然语言数据。 自然语言处理…

《Linux实践及应用》

2019独角兽企业重金招聘Python工程师标准>>> 《Linux实践及应用》 本书以RedHat 9.0为蓝本&#xff0c;系统地介绍Linux的基础知识、Linux系统的安装与配置、常用命令&#xff0c;以及如何进行Linux系统管理和基本的网络服务设置&#xff08;包括如何设置DNS服务器、…

找不到包含 OwinStartupAttribute 的程序集

2019独角兽企业重金招聘Python工程师标准>>> 尝试加载应用时出现了以下错误。 找不到包含 OwinStartupAttribute 的程序集。找不到包含 Startup 或 [AssemblyName].Startup 类的程序集。 若要禁用 OWIN 启动发现&#xff0c;请在 web.config 中为 appSetting owin:A…

Imagination 推新款GPU IP,首次实现桌面级光线追踪效果

游戏界被炒得最热的概念可能就是光线追踪技术了&#xff0c;不仅仅是PC端的游戏。光线追踪所展示出来的画面效果也确实惊艳&#xff0c;可以让我们感叹到图像技术达到的一个新高度。 但是实际上&#xff0c;光线追踪并不是一个新技术。10年前&#xff0c;光追就是游戏玩家茶余…

percent之集合

2019独角兽企业重金招聘Python工程师标准>>> 这个留到明天再来写吧,今天把hub剩下的坑填掉. 转载于:https://my.oschina.net/u/2011113/blog/416458

Mr. Process的一生-Linux内核的社会视角 (2)启动

原文地址&#xff1a; http://www.manio.org/cn/startup-of-linux-view-of-society.html 其实这才应该是这一系列文章的第一节&#xff0c;因为这篇文章讲的是盘古开天地的事。话说Mr. Process是一个现代人&#xff0c;但是&#xff0c;只要是人&#xff0c;总该有个祖先。人们…

深入研究ConcurrentHashMap 源码从7到8的变迁

ConcurrentHashMap是线程安全且高效的HashMap 1 为什么要使用ConcurrentHashMap 线程不安全的HashMap HashMap是Java中最常用的一个Map类&#xff0c;性能好、速度快&#xff0c;但不能保证线程安全&#xff0c;它可用null作为key/value HashMap的线程不安全主要体现在resize时…

IANA定义的常见服务的端口号列表

最新明细&#xff1a;http://www.iana.org/assignments/port-numbers 几个重要常见端口&#xff1a; 21 FTP 22 SSH 80 HTTP 443 HTTPS 1433 MSSQLserver 3306 MySQL 11211 memcached

oracel 服务详细介绍

中的方法成功安装Oracle 11g后&#xff0c;共有7个服务&#xff0c; 这七个服务的含义分别为&#xff1a; 1. Oracle ORCL VSS Writer Service&#xff1a; Oracle卷映射拷贝写入服务&#xff0c;VSS&#xff08;Volume Shadow Copy Service&#xff09;能够让存储基础设备&…

使用 Python 开发一个恐龙跑跑小游戏,玩起来

作者 | 周萝卜 来源 | 萝卜大杂烩 相信很多人都玩过 chrome 浏览器上提供的恐龙跑跑游戏&#xff0c;在我们断网或者直接在浏览器输入地址“chrome://dino/”都可以进入游戏 今天我们就是用 Python 来制作一个类似的小游戏 素材准备 首先我们准备下游戏所需的素材&#xff0c;比…

了解和入门注解的应用

2019独角兽企业重金招聘Python工程师标准>>> 一、概述 jdk的java.lang包中提供的最基本的annotation 1、SuppressWarnings("deprecation") package staticimport.annotation;SuppressWarnings("deprecation") public class AnnotationTest {pub…

Linux下开发优秀链接

不得不说CSDN博客这次改版变化很大&#xff0c;但是友情链接功能太脆弱了。 只有自己写个帖子&#xff0c;不断更新吧。Linux基础 Linux内核mirrors163LVS中文站点 孙海龙 howtoforge.com 地中海东岸的蒲公英 服务器运维与网站架构 Nginx中文维基 ACME Bory.Chan Tim[后端技术]…

Q 版老黄带着硬核技术再登场,有点可爱,很有东西

编译 | 禾木木 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 看到下面这个老黄是不是觉得很Q~ 11月9日&#xff0c;GTC 大会再次来了&#xff0c;英伟达创始人兼CEO黄仁勋再次从自己虚拟厨房走出来。 本次 GTC 大会都有哪些亮点呢&#xff1f; Q 版黄仁勋 英伟达展…

linux第七章《档案与目录管理》重点回顾

转载于:https://www.cnblogs.com/wubingshenyin/p/4514969.html

Effective java 43返回零长度的数组或者集合而不是null

转载于:https://www.cnblogs.com/limingxian537423/p/8391285.html

《Unix网络编程卷1-套接字联网API》第一个例子编译 不通过问题解决

《Unix网络编程卷1-套接字联网API》是本好书。 但是第一个例子不是很好编译。 需要如下步骤&#xff1a; 本人机器CentOS 5.4 1.下载源码 unpv13e解压到任意目录 然后按其readme文件操作./configure # try to figure out all implementation differencescd lib # bu…

angularJs的学习笔记-01(创建项目)

1&#xff0c;进入angular-phonecat目录 执行下面命令 git checkout -f step-0 然后访问 http://localhost:8000/app/ 页面出现 “Nothing here yet!” 现在就可以自己创建HTML&#xff0c;编写angular了 app/index.html <!doctype html> <html lang"en"…

一文搞定深度学习建模预测全流程(Python)

作者 | 泳鱼来源 | 算法进阶本文详细地梳理及实现了深度学习模型构建及预测的全流程&#xff0c;代码示例基于python及神经网络库keras&#xff0c;通过设计一个深度神经网络模型做波士顿房价预测。主要依赖的Python库有&#xff1a;keras、scikit-learn、pandas、tensorflow&a…

第163天:js面向对象-对象创建方式总结

面向对象-对象创建方式总结 1、 创建对象的方式&#xff0c;json方式 推荐使用的场合&#xff1a; 作为函数的参数&#xff0c;临时只用一次的场景。比如设置函数原型对象。 1 var obj {};2 //对象有自己的 属性 和 行为3 // 属性比如&#xff1a; 年龄、姓名、性别4 // 行…

一个从四秒到10毫秒,花了1年的算法问题?

原文:一个从四秒到10毫秒&#xff0c;花了1年的算法问题&#xff1f;五一后的第一周&#xff0c;由于搬家腰扭伤了&#xff0c;没注意导致压迫神经&#xff0c;躺在床上休息了好几天。所以没事就挂 QQ&#xff0c;一个网友突然问了我一个算法问题。所以有了这篇文章。感触很深&…

xinetd 说明

xinetd 是什么在linux中一些不长期使用的服务&#xff08;不重要的服务&#xff1f;&#xff09;没有被作为单独的守护进程在开机时启用&#xff0c;linux把这些服务监听端口全部由一个独立的进程xinetd集中监听&#xff0c;当收到相应的客户端请求之后&#xff0c;xinetd进程就…

英特尔携手中科院计算所建立中国首个 oneAPI 卓越中心

11月12日&#xff0c;在第三届中国超级算力大会&#xff08;ChinaSC 2021&#xff09;上&#xff0c;英特尔与中国科学院计算技术研究所共同建立中国首个 oneAPI 卓越中心&#xff0c;来扩大 oneAPI 对中国本土国产硬件的支持及使用oneAPI来开发全栈式开源软件。 在上个月刚结…

前端学习资源分享

2019独角兽企业重金招聘Python工程师标准>>> 推荐大神文章(文字教程) 1 综合类 前端知识体系前端知识结构Web前端开发大系概览Web前端开发大系概览-中文版智能社 - 精通JavaScript开发JavaScript中的this陷阱的最全收集--没有之一JS函数式编程指南腾讯移动Web前端知…