查看原文
其他

【爬虫实战】“我们,继续新故事”——爬取LOL英雄皮肤

爬虫俱乐部 Stata and Python数据分析 2022-03-15

本文作者:王玉婷,中南财经政法大学金融学院

本文编辑:石   艳

技术总编:王子一

爬虫俱乐部云端课程

  爬虫俱乐部于2020年暑期在线上举办的Stata与Python编程技术训练营和Stata数据分析法律与制度专题训练营已经圆满结束啦~应广大学员需求,我们的课程现已在腾讯课堂全面上线,且继续提供答疑服务。现在关注公众号并在朋友圈转发推文《来腾讯课堂学Stata和Python啦》或《8月Stata数据分析法律与制度专场来啦!》,即可获得600元课程优惠券,集赞50个再领200元课程优惠券!(截图发至本公众号后台领取)原价2400元的课程,现在只要1600元!




一、导读



英雄联盟(League of Legends)是美国拳头游戏于2009年开发的一款MOBA竞技网游,于2011年由腾讯公司在国内代理发行。在端游的黄金时代,英雄联盟在国内外掀起一股电竞旋风,打造了连接世界的独特电竞文化。随着手游的兴起,端游页游逐渐式微,眼看着王者荣耀荣登“国民第一手游”,就连QQ飞车都开发了手游版,LOL老玩家们翘首以盼多年,终于,今年2月9月,LOL手游通过了2021年首批游戏进口审批。

今天,笔者将与各位读者前往英雄联盟官方网站爬取全部154位英雄的高清皮肤图片,一同回忆与队友“并肩作战”的青春岁月。





二、爬虫实战



首先,我们进入腾讯代理的英雄联盟首页(https://lol.qq.com/main.shtml),从首页左上角游戏资料进入资料库,可以看到英雄联盟的所有英雄列表。在此页面上按下F12,打开开发者页面,Ctrl+R刷新后找到含有全部英雄ID的hero_list.js文件(https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js)。

我们使用json库将该文件的英雄ID转换为Python对象,比如字典、列表,以便在后续的循环程序中使用。

1# 获得英雄ID的json文件
2import requests as req
3import json
4
5# 使用requests库获取网页源代码
6js_url = "https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js"
7hero_html = req.get(js_url).content
8hero_js=hero_html.decode("unicode-escape")  # 解码为中文
9
10# 使用json库将json文件转换为Python对象-字典
11hero_dic = json.loads(hero_js)
12
13# 利用字典的get方法获取key=hero的值,get获得的hero是一个大列表,即上图中第2个红框的部分
14hero = hero_dic.get("hero")
15
16# 循环提取每个英雄的heroId
17heroId = []
18for h in hero:
19    heroId.append(h.get("heroId"))
20
21# 查看结果
22print(heroId)
运行上述程序,我们可以获得一个heroId的列表,如下图所示:
别忘了我们的目的:获得所有英雄的皮肤。现在我们点击任意一名英雄的头像,这里我们以黑暗之女--安妮为例,进入该英雄的详情页面,打开开发者页面,找到1.js1表示该英雄的heroId)文件,该json文件包含了安妮的所有皮肤(skins)信息,如图。


同样地,我们使用json库将该json文件抓取下来。和前一个json文件不一样的是:包含skins的文件不是一个严格标准的json,其中的反斜杠\和双引号"在loads时会引发报错,因此利用正则表达式清洗处理源网页代码。

1import re
2
3url = "https://game.gtimg.cn/images/lol/act/img/js/hero/1.js"
4skins_html = req.get(url,timeout = 1).content
5skins_js = skins_html.decode("unicode-escape")
6
7# 使用json转换时,js文件中的\和"会引起报错
8skins_js = re.sub('''\\\\(?=/)''',"",skins_js)  # 正则替换\时要经过多重转义,或者使用r  
9skins_js = re.sub('''(?<=[\u4e00-\u9fa5]|。)"(?!,|])''',"'",skins_js)  # 替换特定文本处的双引号
10skins_js = re.sub('''(?<=[\u4e00-\u9fa5]:)"(?!,|])''',"'",skins_js)  # 替换特定文本处的双引号
11skins_js = re.sub('''(?<=\d%)"(?!,"|])''',"'",skins_js) # 替换特定文本处的双引号
12
13# strict选项设置skins_js不是一个严格的json文本
14skins_dic = json.loads(skins_js,strict=False)
15skins = skins_dic.get("skins")

点开任意一个皮肤编号,我们所需要的只有皮肤的高清大图url(mainImg)和皮肤名称(name)。

1skinName = []
2skinImage = []
3for skin in skins:
4    if skin.get("mainImg") == "":  # 剔除没有mainImg的皮肤
5        continue
6    else:
7        skinName.append(skin.get("name"))
8        skinImage.append(skin.get("mainImg"))
9print(skinName,skinImage)
OK,现在“万事俱备,只欠东风”,使用requests库循环下载“安妮”的所有皮肤,并将图片命名为对应的皮肤名称。为了避免请求超时导致下载失败,我们使用try...except...来设置三次重试。同时,为了避免下载过快导致ip被封,我们使用time库设置每下载一张图片间隔2秒。 1# 下载英雄皮肤保存到本地
2import time
3
4for sn,si in zip(skinName,skinImage):
5# 连接超时重试
6    i = 0
7    while i < 3:
8        try:
9            image = req.get(si,timeout=5).content
10            # 打开图片文件,设置模式为"wb"(写入二进制)
11            with open(r"./lol全英雄皮肤/%s.jpg" %sn,"wb"as file:
12                file.write(image)
13                print("已下载%s皮肤" %sn)
14                file.close()
15                break
16        except req.exceptions.RequestException as e:
17            i += 1
18            print("%s连接超时,重新连接" %sn)
19    time.sleep(2)  # 间隔2秒
20print("安妮图片已下载完成"
最后,我们利用第一步获取的heroId,循环下载所有英雄皮肤的高清大图,完整程序如下: 1import re
2import json
3import requests as req
4import time
5
6skinName = []
7skinImage = []
8for id in heroId:
9    print("正在获取heroId为%s的皮肤url及其名称" %id)
10    url = "https://game.gtimg.cn/images/lol/act/img/js/hero/%s.js" %id
11    i=0
12    while i < 3:
13        try:
14            skins_html = req.get(url,timeout = 2).content
15            break
16        except Exceptions as e:
17            i += 1
18            print("%s连接失败,重新连接" %id)
19    skins_js = skins_html.decode("unicode-escape")
20
21    # 使用json转换时,js文件中的\和"会引起报错
22    skins_js = re.sub('''\\\\(?=/)''',"",skins_js)  # 正则替换\时要经过多重转义  
23    skins_js = re.sub('''(?<=[\u4e00-\u9fa5]|。)"(?!,|])''',"'",skins_js)  # 替换掉文本中的双引号
24    skins_js = re.sub('''(?<=[\u4e00-\u9fa5]:)"(?!,|])''',"'",skins_js)  # 替换掉文本中的双引号
25    skins_js = re.sub('''(?<=\d%)"(?!,"|])''',"'",skins_js) # 替换掉文本中的双引号
26
27    # strict选项设置skins_js不是一个严格的json文本
28    skins_dic = json.loads(skins_js,strict=False)
29    skins = skins_dic.get("skins")
30
31    for skin in skins:
32        if skin.get("mainImg") == "":
33            continue
34        else:
35            skinName.append(skin.get("name"))
36            skinImage.append(skin.get("mainImg"))
37    time.sleep(2)
38
39# 下载英雄皮肤保存到本地
40for sn,si in zip(skinName,skinImage):
41    i = 0
42    while i < 3:
43        try:
44            image = req.get(si,timeout=5).content
45            with open(r"./lol全英雄皮肤/%s.jpg" %sn,"wb"as file:
46                file.write(image)
47                print("已下载%s皮肤" %sn)
48                file.close()
49                break
50        except req.exceptions.RequestException as e:
51            i += 1
52            print("%s连接超时,重新连接" %sn)
53    time.sleep(2)
54print("全部图片已下载完成")   
这样,全部的英雄皮肤都下载下来啦~

文末,笔者选取多名人气英雄制作了气势磅礴的英雄群像,与官方宣传片《我们,继续新故事》交相呼应。

以上就是本期的全部内容啦,各位亲,别忘记点赞、转发、关注呦~





对我们的推文累计打赏超过1000元,我们即可给您开具发票,发票类别为“咨询费”。用心做事,不负您的支持!
往期推文推荐

“人像动漫化”—Python实现抖音特效

跨框架合并数据|frlink的用法,你get到了吗

《唐探3》做错了什么?|来自150万字影评的证据

爬虫俱乐部年度总结|《请回答2020》

春节假期临近,来爬爬豆瓣看看有什么好剧
putdocx生成Word文档so easy!

模糊匹配我只用这一招!

利用tushare获取财务数据

爬虫实战|Selenium爬取微信公众号标题与链接

轻轻一点,就知有没有|rqrs命令介绍

强大的正则表达式

自动群发邮件(二)——附带附件

自动群发邮件--email和smtplib基本模块的使用

批量处理变量名和标签的小方法

计算工作日的小能手——workdays

Seminar | 企业错报与银行贷款合同

Seminar | 共同基金行业的性别歧视
Seminar | 来自女儿的塑造:高管、女性社会化与企业社会责任

小贴士:Markdown的基本语法

听说相貌也能量化 | 调用百度人脸检测API实现颜值打分

列出指定属性的变量|findname命令比ds命令

新一代的标签转码小能手
【爬虫实战】亚马逊网站Top100畅销书爬取

Json文件好帮手——JsonPath

数据转置pro之sxpose2
文件"搬家"小助手:mvfiles
关于我们


微信公众号“Stata and Python数据分析”分享实用的stata、python等软件的数据处理知识,欢迎转载、打赏。我们是由李春涛教授领导下的研究生及本科生组成的大数据处理和分析团队。

此外,欢迎大家踊跃投稿,介绍一些关于stata和python的数据处理和分析技巧。
投稿邮箱:statatraining@163.com
投稿要求:
1)必须原创,禁止抄袭;
2)必须准确,详细,有例子,有截图;
注意事项:
1)所有投稿都会经过本公众号运营团队成员的审核,审核通过才可录用,一经录用,会在该推文里为作者署名,并有赏金分成。
2)邮件请注明投稿,邮件名称为“投稿+推文名称”。
3)应广大读者要求,现开通有偿问答服务,如果大家遇到有关数据处理、分析等问题,可以在公众号中提出,只需支付少量赏金,我们会在后期的推文里给予解答。

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存