Python爬取斗鱼英雄联盟所有玩adc的主播房间信息并用redis存储数据
最近想要用巩固下json数据的提取以及数据的存储,于是选了斗鱼作为研究对象。。
下面就是所有要爬取的adc,当然有个别adc没人玩就不爬不了。
首先观察下虚空之女和赏金猎人这两个英雄的直播页面什么差异。
可以发现,两者的url并没有差异,那么就不能从html页面下手了,接下来再看看XHR和json。
在XHR的getTagRoomlist中发现了直播间相关的数据
然后再观察Headers中的内容
这是虚空之女的直播间页面url:
https://www.douyu.com/dir_new/getTag2RoomList?tag2_id=247&page=1&cate2_id=1
然后下面是赏金猎人的:
https://www.douyu.com/dir_new/getTag2RoomList?tag2_id=241&page=1&cate2_id=1
可以发现他们仅有tag2_id不同。那么只要获取到这个id的list就能请求相关的数据了。但是观察了一下左边这一栏所有的内容都没有发现和英雄对应的id有关的信息。
折腾了一会发现要重新刷新当前页面才能看到id的信息,也就是不进行任何筛选的情况下才能看到。
所有的tag_id都在第一个url中:https://www.douyu.com/dir_new/getAllTag1withtag2list?cate2_id=1
那么思路就是先请求这个url获取所有的英雄对应的id,然后根据id组建新的url,再各个请求,获取信息。
首先导入必要的包,最后数据存储用redis(最近学的这个,后续还会更mySQL)
import requests
import redis
base_url = 'https://www.douyu.com/dir_new/getAllTag1withtag2list?cate2_id=1' # 用来请求id的url
room_url = 'https://www.douyu.com/dir_new/getTag2RoomList?tag2_id={}&page=1&cate2_id=1' #待拼接的url
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36'
}
获取英雄的id
def get_id():
response = requests.get(base_url, headers=headers)
#观察json中的格式结构进行提取
info = response.json()['data'][4]['tag2_list']
return info
最后返回的就是它,一个list,后面只需要循环提取就ok。
获取房间信息
def get_room_info(hero_id, hero_name):
url = room_url.format(hero_id)
response = requests.get(url, headers=headers)
#仅提取其中的room_list信息
room_info = response.json()['data']['room_list']
total_room = []
for item in room_info:
each_room = dict()
each_room['room_id'] = item['rid'] #房间id
each_room['room_name'] = item['rn'] #房间名
each_room['room_host'] = item['nn'] #主播
each_room['hero_name'] = hero_name #英雄名称
# 把room的信息合并成一个字典
total_room.append(each_room)
return total_room
主程序
包括函数的调用以及数据的存储
#调用函数获取id
info = get_id()
#调用redis数据库
client = redis.StrictRedis(host='XXX.X.X.X', port='6379')
for item in info:
hero_id = item['tag2_id'] #获取英雄id
hero_name = item['tag2_name'] #获取英雄名称
#调用函数获取room信息
hero_room = get_room_info(hero_id, hero_name)
#由于某些英雄没有主播在玩,也就没有room信息,所以要判断一下获取的hero_room是否为空
if hero_room != '':
#由于字典不支持迭代,所以将其转化为list类型再进行迭代
hero_room = list(hero_room)
for ind, hero in enumerate(hero_room):
#作为哈希数据写入redis,每一个直播间作为一个field
client.hmset(hero_name+str(ind), {'room_id': hero['room_id'], 'room_name': hero['room_name'], 'room_host': hero['room_host']})
最后测试一下是否导入成功
import redis
client = redis.StrictRedis(host='127.0.0.1', port='6379')
print(client.hget('寒冰射手1', 'room_id'))
返回
b'7153773'
Bingo!