腾讯视频的弹幕怎么去掉的(用Python爬去腾讯视频弹幕实战步骤介绍)

首页教程更新时间:2023-05-31 22:58:06

腾讯视频的弹幕怎么去掉的,用Python爬去腾讯视频弹幕实战步骤介绍(1)

本⽂文以腾讯视频《天⾏行行九歌》为例,详细解析腾讯视频弹幕爬取的细节和难点, 相对于⼀一般电影或者电视剧评论,弹幕都是在特定剧情下观众随性发出来的,所以弹幕能够贴合剧情,进⾏更多有意思的脑洞分析。

写爬⾍需要理清目标据和网址的变化规律,随后再去解决细节的数据定位和抓取,往事半功倍。 接下来先看看爬⾍的⼀般步骤:

前戏爬虫一般步骤:

第一步:明确需求

明确需求,确定需要抓取的字段

第二步:寻找目标URL

分析⽹站,寻找⽬标URL

第三步: 确定参数与请求方式

分析⽬标URL参数,请求方式(get,post)

第四步: 发起请求

1.设置请求头(User-Agent,Cookie,Host) 2.实例例化⼀一个Request对象(request.Request) 3.根据实例化的Request对象,使用request.get()或者post()⽅法发起请求

第五步: 反爬与反反爬

1.基于headers的反爬:基于⽤户请求的headers反爬是最常见的反爬机制,在请求头headers中,包含很多键值对,服务器会根据这些键值对进⾏反爬。 2.基于用户行为的反爬:检测用户的行为是否正常,如访问频率 3.基于动态页面的反爬:使用动态网页,动态生成数据,或者动态加载,⽆法从源码直接查看数据 4.基于验证码的反爬:检测到异常访问可能会弹出验证码 5.基于加密的反爬:通过js来对数据进⾏加密或者通过css字体加密

第六步:处理响应结果

1.Ajax请求得到的⼀一般是json数据,使⽤用json模块处理,使用json.loads将json字符串串,转为pytho n数据类型 2.对于非结构化数据(数据在html⻚页⾯面中),可以使用re正则模块提取数据(xpath,BeautifulSoup,pyquery) 3.如果还有其他url需要发起请求则继续发起请求

第七步: 数据的持久化

1.⽂文件存储(json,csv,txt) 2.数据库存储(MongoDB,MySQL,Redis) 开始你的表演

1、数据定位

腾讯视频的弹幕怎么去掉的,用Python爬去腾讯视频弹幕实战步骤介绍(2)

打开腾讯是视频《天⾏行行九歌》视频随便便选取一集,观察我们需要抓取的弹幕,可以明显看出来弹幕不不是在视 频上的⽽是浮动在视频上⾯面,而且弹幕在视频播放之后才滚动加载,所以我们大概能得出弹幕是JS异步加载 的。

按F12审查元素, 观察Network是的请求,播放开始后出现了了⼤量请求,除了大部分图片外我们发现了⼀个 ⽐较特殊的请求 "danmu" ,打开这个请求后果然这就是我们要的弹幕数据。

腾讯视频的弹幕怎么去掉的,用Python爬去腾讯视频弹幕实战步骤介绍(3)

获取到弹幕数据的URL地址

腾讯视频的弹幕怎么去掉的,用Python爬去腾讯视频弹幕实战步骤介绍(4)

2、弹幕URL规律分析

在找⽹址规律的时候,有⼀一个⼩小技巧,就是尝试暴力删掉⽬标网址中不影响最终结果的部分参数,再从最精简的⽹址中寻找规律。

我们观察请求参数的时候注意下Requet Method。这⾥是get请求也就是可以直接在浏览器器请求URL,看能否 能拿到数据。

第⼀一个URL:

https://mfm.video.qq.com/danmu?otype=json&callback=jQuery19109468267287377041_1563457399127&target_id=4005600990&vid=a0031sxc3f8&session_key=33792,4336,1563458184&timestamp=75&_=1563457399193

浏览器器上请求结果:

腾讯视频的弹幕怎么去掉的,用Python爬去腾讯视频弹幕实战步骤介绍(5)

开始暴⼒删除⽆关参数,URL?后⾯拼接的参数有 callback, targetid, sessionkey, timestamp, 。 网址最后⼀串数据好像是时间戳,删了试试 ,结果不变,是无关参数。sessiongkey到底影不影响呢? 不知道可以删除试试。

最后精简成下⾯面这个URL,只有target_id, timestamp两个是必须参数

https://mfm.video.qq.com/danmu?target_id=4005600990&vid=a0031sxc3f8&timestamp=15

将第二,三, 四个请求拿出来精简

https://mfm.video.qq.com/danmu?target_id=4005600990&vid=a0031sxc3f8&timestamp=45https://mfm.video.qq.com/danmu?target_id=4005600990&vid=a0031sxc3f8&timestamp=75https://mfm.video.qq.com/danmu?target_id=4005600990&vid=a0031sxc3f8&timestamp=105

对⽐很容易易找到规律,从第一⻚页到第⼆页,timestamp值从15变到了45,第二页到第三⻚页从45到75,target_id不不变。这个规律我们可以大胆猜测这个 timestamp 值是控制页数的,并且起始值是15每30秒更更新⼀次。

一集视频弹幕有多少页呢?如何获取最后⼀一个timestamp的值?这里有个小技巧,先将视频拉倒最后观察timestamp的值是多少,然后给timestamp⼀一个远远超出最后这个值到浏览器器请求,返回数据为count值为0,说明弹幕已经加载完。

腾讯视频的弹幕怎么去掉的,用Python爬去腾讯视频弹幕实战步骤介绍(6)

接下来获取一集弹幕,只需要使⽤用while循环timetamp给一个步长30的变量,到最后获取count为0的时候退出。

就可以获取到一集的所有弹幕。

3、不同集之间URL规律分析

一集的弹幕规律搞清楚之后,我们来研究不同集之间的URL规律。

第73集精简后的URL

https://mfm.video.qq.com/danmu?target_id=4005600990&vid=a0031sxc3f8&timestamp=15

第72集精简后的URL

https://mfm.video.qq.com/danmu?&target_id=3991095756&vid=l0031n48946&timestamp =465

对⽐不同集之间的URL发现targetid值是不一样的,猜测这个targetid决定的集数。timestamp 规律之前已经找 到,这⾥我们将精⼒投⼊到targetid中寻找它的规律,但我们研究了几集之后发targetid除了了 &vid= 这 一串其他的毫⽆规律。

那我们现在将 target_id 分成两半,我将它们称之为前缀ID,后缀ID。但从URL上⾯面我们是找不到有⽤用线索 了,这时候我们必须转换思路回到⻚面上来。

后缀ID

在浏览视频页面的时候,我们发现播放视频时在播放屏右边总会显示全部集数,点击对应的集数就会进行相应的换集跳转,所以我们有理理由相信target_id相关的东⻄就藏在其中。

腾讯视频的弹幕怎么去掉的,用Python爬去腾讯视频弹幕实战步骤介绍(7)

检查元素,果然不出我所料html⻚面里就藏着后缀ID。

腾讯视频的弹幕怎么去掉的,用Python爬去腾讯视频弹幕实战步骤介绍(8)

浏览页面源代码的时候我们发现HTML源码里面有这样一段JS,包含了所有集的后缀ID,从⾥⾯去获取会更更好

(注意F2是正常的已上线的集,F0可能是脏数据或者是没上线的所以我们只需要去F2的数据即可获取到所有的后缀ID)

腾讯视频的弹幕怎么去掉的,用Python爬去腾讯视频弹幕实战步骤介绍(9)

前缀ID

但遗憾的是前缀ID在⻚面⾥面并没有找到,既然页面上没有,那我们再转换下思路路。页面上没有那么有可能是点击跳集的时候才请求前缀ID。

播放视频F12在不同集之间切换继续观察Network的请求, 每次切换不同集的时候有一个请求 regist 进⼊了我们得视线点击进去看果然⾥面有我们需要的前缀ID。

腾讯视频的弹幕怎么去掉的,用Python爬去腾讯视频弹幕实战步骤介绍(10)

切换不同集观察URL变化,没有什么变化都是同⼀一个URL。

https://access.video.qq.com/danmu_manage/regist?vappid=97767206&vsecret=c0bdcbae120669fff425d0ef853674614aa659c605a613a4&raw=1

但是我们发现每一集的请求都有⼀个参数变化 vecIdList,仔细一看这不就是我们的后缀ID?(注意这⾥里里使⽤用post请求,参数是json格式)

{"wRegistType":2,"vecIdList":["s0019ub7cbi"],"wSpeSource":0,"bIsGetUserCfg":1,"mapExtData":{"s0019ub7cbi":{"strCid":"rm3tmmat4li8uul","strLid":""}}}

也就是拿到后缀id之后,再次请求获取到后缀ID。

到这⾥我们已经可以获取到⼀个完整的target_id,所有的参数以及规律都摸清楚了,已经跃欲试?别急梳理下思路。

4、思路梳理

第一步,搞清楚单集内部弹幕网址的动态变化,只需要改变timestamp的值即可循环爬取单集所有内 容。

第二步,发现不同集之间有一个参数target_id 是变量量,除了 &vid= 一样外,没有规律,我们将其 分成前缀ID和后缀ID。

第三步,任意⼀集网⻚中都能直接找到所有剧集的后缀ID,但⽆法获取前缀ID。

第四步,通过分析发现,要获取前缀ID需要通过后缀ID发送请求获取,两个ID都获取到之后拼接成target_id=前缀ID &vid= 后缀ID

第五步,所有参数已经获取,URL规律已经搞清楚就可以写代码了了

卷起袖子,撸代码

import time import requests import pandas as pd import re import json from urllib import parse import os # 请求头 headers = { "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36" } def get_postfix_id(url): """ 从播放页获取后缀ID :param url: 播放页的url :return postfix_list: 返回后缀ID """ html = requests.get(url, headers=headers).content.decode("utf-8") # 用正则提取每一集的数据 result = re.search(r'"nomal_ids":(.*?)]', html, re.S).group(1) "]" postfix = json.loads(result) postfix_list = [] # 提取前缀ID for i in postfix: if i["F"] != 0: postfix_list.append(i["V"]) print("共%s集" % len(postfix_list)) return postfix_list def get_prefix_id(url, postfix_list): """ 获取前缀ID :param url: 获取前缀ID请求url固定为 prefix_url :param postfix_list: 后缀ID :return: """ prefix_list = [] for index, vid in enumerate(postfix_list, 1): # 构造每一集的参数 param_json = {"wRegistType": 2, "vecIdList": [vid], "wSpeSource": 0, "bIsGetUserCfg": 1, "mapExtData": {"%s" % vid: {"strCid": "rm3tmmat4li8uul", "strLid": ""}}} # 请求 result = requests.post(url, headers=headers, json=param_json).text data = json.loads(result.strip("data=")) url_param = data['data']["stMap"][vid]["strDanMuKey"] prefix_id = parse.parse_qs(url_param)['targetid'] print("获取到第%s集,前缀ID=%s" % (index, prefix_id[0])) prefix_list.append(prefix_id[0]) return prefix_list def get_danmu(prefix_list, postfix_list): """ 请求弹幕 :param prefix_list: 前缀ID :param postfix_list: 后缀ID :return:弹幕 """ k = 1 for prefix_id, postfix_id in zip(prefix_list, postfix_list): timestamp = 15 print("开始抓取第%s集弹幕" % k) # 构造弹幕请求url while True: time.sleep(1) # 让请求慢点 danmu_url = "https://mfm.video.qq.com/danmu?target_id={}&vid={}&timestamp={}".format(prefix_id, postfix_id, timestamp) try: result = requests.get(danmu_url, headers=headers).json() if result["count"] == 0: print("第%s集抓取完毕" % k) k = 1 break # 遍历获取目标字段 for i in result['comments']: content = i['content'] # 弹幕内容 name = i['opername'] # 用户名 upcount = i['upcount'] # 点赞数 user_degree = i['uservip_degree'] # 会员等级 timepoint = i['timepoint'] # 发布时间 comment_id = i['commentid'] # 弹幕ID data = {'用户名': [name], '内容': [content], '会员等级': [user_degree], '评论时间点': [timepoint], '评论点赞': [upcount], '评论id': [comment_id]} # 字典无序,防止写入表格乱序 data = dict(sorted(data.items(), key=lambda x: x[0])) danmu_data = pd.DataFrame(data) # 保存到csv if not os.path.exists("danmu.csv"): # 不存在就写入,要写表头 danmu_data.to_csv("danmu.csv", mode="w", header=True) # 存在就追加,不写表头 danmu_data.to_csv("danmu.csv", mode="a", header=False) except Exception as e: print("抓取失败 %s" % danmu_url) print("抓取成功 %s" % danmu_url) timestamp = 30 if __name__ == '__main__': video_url = "https://v.qq.com/x/cover/rm3tmmat4li8uul/j0031xbgr7x.html" prefix_url = "https://access.video.qq.com/danmu_manage/regist?vappid=97767206&vsecret=c0bdcbae120669fff425d0ef853674614aa659c605a613a4&raw=1 " postfix_list = get_postfix_id(video_url) prefix_list = get_prefix_id(prefix_url, postfix_list) get_danmu(prefix_list, postfix_list) 结果

腾讯视频的弹幕怎么去掉的,用Python爬去腾讯视频弹幕实战步骤介绍(11)

IT技术研习社,专注互联网技术研究与分享,喜欢的朋友可以点击【关注】;把经验传递给有梦想的人;

,
图文教程
相关文章
热门专题
推荐软件
奇热小说
奇热小说
下载
QQ2019手机版
QQ2019手机版
下载
王者荣耀
王者荣耀
下载
百度浏览器迷你版
百度浏览器迷你版
下载
2345浏览器手机版
2345浏览器手机版
下载
网易邮箱
网易邮箱
下载
爱奇艺
爱奇艺
下载
网易云音乐
网易云音乐
下载
WPSOffice
WPSOffice
下载
优酷
优酷
下载
谷歌浏览器(Chrome)
谷歌浏览器(Chrome)
下载
迅雷看看播放器
迅雷看看播放器
下载
UC浏览器
UC浏览器
下载
QQ音乐
QQ音乐
下载
阿里旺旺买家版v9.12.10C官方版
阿里旺旺买家版v9.12.10C官方版
下载
360安全卫士v12.1官方版
360安全卫士v12.1官方版
下载
猜你喜欢
我是神手游
我是神手游
下载
山海月中歌
山海月中歌
下载
海外寻医
海外寻医
下载
HDDRegenerator中文版v2014
HDDRegenerator中文版v2014
下载
惠妁
惠妁
下载
幻刃录bt版
幻刃录bt版
下载
极道之龙
极道之龙
下载
科普君的对答app
科普君的对答app
下载
酷繁抢币助手
酷繁抢币助手
下载
安眠七项修改器
安眠七项修改器
下载
荣耀战国高爆版
荣耀战国高爆版
下载
我们之间抽个棍
我们之间抽个棍
下载
星际飞船大战
星际飞船大战
下载
守望先锋掌游宝iPad版V1.0.0
守望先锋掌游宝iPad版V1.0.0
下载
环世界1.0射击靶场MOD
环世界1.0射击靶场MOD
下载
空之翼VRv2.2.0
空之翼VRv2.2.0
下载