其他
【爬虫实战】“我们,继续新故事”——爬取LOL英雄皮肤
本文作者:王玉婷,中南财经政法大学金融学院
本文编辑:石 艳
技术总编:王子一
爬虫俱乐部云端课程
一、导读
英雄联盟(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.js
(1
表示该英雄的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("全部图片已下载完成")
这样,全部的英雄皮肤都下载下来啦~文末,笔者选取多名人气英雄制作了气势磅礴的英雄群像,与官方宣传片《我们,继续新故事》交相呼应。
以上就是本期的全部内容啦,各位亲,别忘记点赞、转发、关注呦~“人像动漫化”—Python实现抖音特效
《唐探3》做错了什么?|来自150万字影评的证据
爬虫俱乐部年度总结|《请回答2020》
模糊匹配我只用这一招!
利用tushare获取财务数据
爬虫实战|Selenium爬取微信公众号标题与链接
强大的正则表达式
自动群发邮件(二)——附带附件
自动群发邮件--email和smtplib基本模块的使用
计算工作日的小能手——workdays
Seminar | 企业错报与银行贷款合同
小贴士:Markdown的基本语法
听说相貌也能量化 | 调用百度人脸检测API实现颜值打分
列出指定属性的变量|findname命令比ds命令
Json文件好帮手——JsonPath
微信公众号“Stata and Python数据分析”分享实用的stata、python等软件的数据处理知识,欢迎转载、打赏。我们是由李春涛教授领导下的研究生及本科生组成的大数据处理和分析团队。
1)必须原创,禁止抄袭;
2)必须准确,详细,有例子,有截图;
注意事项:
1)所有投稿都会经过本公众号运营团队成员的审核,审核通过才可录用,一经录用,会在该推文里为作者署名,并有赏金分成。
2)邮件请注明投稿,邮件名称为“投稿+推文名称”。
3)应广大读者要求,现开通有偿问答服务,如果大家遇到有关数据处理、分析等问题,可以在公众号中提出,只需支付少量赏金,我们会在后期的推文里给予解答。