📖 Python 学习笔记
效果
准备
在写代码之前,我们首先要明确我们需要实现的大致功能。除去爬虫这个核心功能外,我们需要对爬取的图片做一定的汇总。
- 首先我们要知道游戏内的所有英雄,我们以英雄为名创建文件夹
- 其次我们要获取壁纸的信息,并解析属于哪个英雄
- 将壁纸下载并放入指定文件夹内
代码以生产者消费者的模式编写,目的是为了让业务分析和 IO 操作分离开,从而提高任务执行效率
了解网页内容
想要获取网页上的信息,当然要先了解网页的内容。获取网页上的内容主要有两种:
- 对于静态页面,我们直接获取页面元素,对页面元素进行解析
- 而大部分情况下,页面是动态的,即通过调用 http 接口,接受返回的信息再对页面进行渲染,那此时我们就要模拟请求从而获得我们想要的信息。
获取所有英雄的信息
我们打开官网地址,找到【英雄资料】点击后会跳转到英雄界面,页面默认展示全部英雄
那么我们接下来的任务就是查找英雄的数据来源
分析界面元素
我使用的是火狐
- 按 F12 打开 开发者工具,点击【查看器】可以看到整个页面的源码
- 将鼠标移动到源码 元素 上 ,页面上对应的内容会有颜色提示
- 或者我们通过点击开发者工具栏,最左侧的小鼠标标志,然后再点击页面上的元素,可以直接定位到 源码 所在的位置
- 通过源码我们可以看到,英雄信息放在 li 标签中
获取源码并解析
通过以上的分析,我们就可以开始进行我们的代码了,获取页面信息并解析的时候要注意:
- 获取页面后的字符集要与源码统一
- BeautifulSoup 真的挺好用
import requests
from urllib import request
from bs4 import BeautifulSoup
def get_rolenames():
#url
url ="https://pvp.qq.com/web201605/herolist.shtml"
# 获取页面元素
html = request.urlopen(url).read()
# 与源码统一编码格式
htmltext = html.decode('gbk')
# 转换成soup
soup = BeautifulSoup(htmltext, "html.parser")
# 获取body内容
body = soup.find('body')
# 获取BODY下面的 第一个div元素 ,根据属性class定位 拥有这个属性的div在页面中是唯一的 后面的代码类似
div_0 = body.find('div',attrs={'class':'wrapper'})
div_1 = div_0.find('div', attrs={'class': 'zkcontent'})
div_2 = div_1.find('div', attrs={'class': 'zk-con-box'})
div_3 = div_2.find('div', attrs={'class': 'herolist-box'})
div_4 = div_3.find('div', attrs={'class': 'herolist-content'})
ul_0 = div_4.find('ul', attrs={'class': 'herolist clearfix'})
# 找到 ul 标签后 里面全是包含英雄信息的 li 标签
for elm in ul_0.select("li"):
# 打印li信息
print(elm)
这里的代码我只写到一半,因为我发现获取到的英雄列表总是比网页上的少。通过观察打印出来的元素信息(网页源码上的没有缩进,看起来很麻烦),找到了原因,这个页面其实是个动态页面,数据是动态加载的。
在源码的 JS代码中有这么一段,通过请求 “/erb201605/js/herolist.json”获取英雄列表,并重新填充 heroContent 元素内容
切换思路,请求接口数据并解析
既然知道了原因,那么我们就得换个思路去获取了,我们通过请求 “/erb201605/js/herolist.json”获取herolist.json文件中的内容并解析
内容如下:
[{
"ename": 105,
"cname": "廉颇",
"title": "正义爆轰",
"new_type": 0,
"hero_type": 3,
"skin_name": "正义爆轰|地狱岩魂"
}, {
"ename": 106,
"cname": "小乔",
"title": "恋之微风",
"new_type": 0,
"hero_type": 2,
"skin_name": "恋之微风|万圣前夜|天鹅之梦|纯白花嫁|缤纷独角兽"
}...]
Python代码:
import json
import requests
from urllib import request
# 公共变量 存放英雄信息
herolist = []
def get_rolenames_2():
global herolist
# 请求地址
herolist_url = "https://pvp.qq.com/web201605/js/herolist.json"
# 请求头 ,尽量模拟网页操作 调取不成功 就把网页上请求该接口时的请求头信息都复制过来
headers_2 = {
"User_Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0",
"Referer": "https://pvp.qq.com/web201605/herolist.shtml"
}
# 请求并接受返回信息
resp = requests.get(herolist_url, headers_2)
# 获得文本内容
resp_txt = resp.text
# 转json
resp_dic = json.loads(resp_txt)
# 英雄名字存放在 cname 属性中
herolist = [heromsg["cname"] for heromsg in resp_dic]
# 最后在列表中添加一个其他,为存放不是英雄皮肤的壁纸
herolist.append("其他")
这一次我们顺利的获取到了所有的英雄信息。
接下来就是获取全部的皮肤壁纸并放到指定的英雄文件夹内,这部分功能将放到下一篇文章中记录。