本文以作者亲身经历为逻辑线讲述爬取过程,方便读者举一反三。
一、明确爬取内容
1. 首先我们打开《爱情公寓5》第一集视频,广告之后,打开控制台(F12),使用 Ctrl+Shift+C 指令,获取 Html 中弹幕元素:
2. 我们看到该部分内容是动态更新的,<div>标签的 status 属性表明了当前元素的播放状态,设想直接请求网页获取Html后进行解析来获取弹幕是不可行的,故我们从网页与服务器的交互进行下手。理所当然,我们想到了控制台的 Network 功能,点开 Netwrok 后,使用 Ctrl+R 指令,重新加载网页:
3. 在茫茫文件中,我们通过过滤器试着查找一下 bullet ,我们可以看到有以下几个文件:
4. 我们观察一下每个 Request URL :
Request URL:
https://cmts.iqiyi.com/bullet/40/00/11298454000_300_5.z?rn=0.41964474120625517&business=danmu&is_iqiyi=true&is_video_page=true&tvid=11298454000&albumid=212447801&categoryid=2&qypid=01010021010000000000
我们对 URL 解析发现,请求的主要部分为:
# https://cmts.iqiyi.com/bullet/tv_id[-4:-2]/tv_id[-2:]/tv_id_300_x.z
# https://cmts.iqiyi.com/bullet/视频编号的倒数4、3位/视频编号的倒数2、1位/视频编号_300_序号.z
# 弹幕文件每5分钟(300秒)向服务器请求一次,故每集弹幕文件数量等于视频时间除以300之后向上取整,实际编程时这里可以简单处理
该文件为.z文件,故我们得先解压后才能看到实际内容。
二、代码编程
1. 获取《爱情公寓5》36集的视频编号(tv_id):
- tv_id.py
import requests
import json
def get_tv_id(aid):
# tv_id列表
tv_id_list = []
for page in range(1, 3):
url = 'https://pcw-api.iqiyi.com/albums/album/avlistinfo?aid=' \
+ aid + '&page='\
+ str(page) + '&size=30'
# 请求网页内容
res = requests.get(url).text
res_json = json.loads(res)
# 视频列表
move_list = res_json['data']['epsodelist']
for j in move_list:
tv_id_list.append(j['tvId'])
return tv_id_list
if __name__ == '__main__':
# 节目id
my_aid = '212447801'
my_tv_id_list = get_tv_id(my_aid)
2. 爬取并解析弹幕:
- bullet.py
import zlib
import requests
tv_id_module = __import__('tv_id')
def get_bullet(tv_id):
for page in range(1, 17):
# https://cmts.iqiyi.com/bullet/tv_id[-4:-2]/tv_id[-2:]/tv_id_300_x.z
url = 'https://cmts.iqiyi.com/bullet/'\
+ tv_id[-4:-2] + '/'\
+ tv_id[-2:] + '/'\
+ tv_id + '_300_'\
+ str(page) + '.z'
print(url)
# 请求弹幕压缩文件
res = requests.get(url).content
res_byte = bytearray(res)
try:
xml = zlib.decompress(res_byte).decode('utf-8')
# 保存路径
path = '../data/' + tv_id + '_300_' + str(page) + '.xml'
with open(path, 'w', encoding='utf-8') as f:
f.write(xml)
except:
return
if __name__ == '__main__':
# 节目id
my_aid = '212447801'
# tv_id列表
my_tv_id_list = tv_id_module.get_tv_id(my_aid)
for i in my_tv_id_list:
get_bullet(str(i))
代码已上传到本人 GitHub :https://github.com/Ambitioner-c/iqiyi_bullet.git