40

用Python爬取B站、腾讯视频、芒果TV和爱奇艺视频弹幕

 3 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzI1MTE2ODg4MA%3D%3D&%3Bmid=2650074902&%3Bidx=1&%3Bsn=1dbf302315500deae51d9e06d364dcf8
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Python网络爬虫与文本数据分析

大家好,我是J哥。

众所周知,弹幕,即在网络上观看视频时弹出的评论性字幕。不知道大家看视频的时候会不会点开弹幕,于我而言,弹幕是视频内容的良好补充,是一个组织良好的评论序列。通过分析弹幕,我们可以快速洞察广大观众对于视频的看法。 

J哥通过一个关于《八佰》的视频弹幕数据,绘制了如下词云图,感觉效果还是可以的。 

mE77n27.png!mobile

海量的弹幕数据不仅可以绘制此类词云图,还可以调用百度AI进行情感分析。那么,我们该如何获取弹幕数据呢?本文运用Python爬取B站视频、腾讯视频、芒果TV和爱奇艺视频等弹幕,让你轻松获取主流视频网站弹幕数据。 

一、B站视频弹幕

1.网页分析

本文以爬取up主硬核的半佛仙人发布的《你知道奶茶加盟到底有多坑人吗?》视频弹幕为例,首先通过以下步骤找到存放弹幕的真实url。

UVRRfyI.png!mobile

简单分析url参数,很显然,date参数表示发送弹幕的时间,其他参数均无变化。因此,只需要改变date参数,然后通过beautifulsoup解析到弹幕数据即可。

2.爬虫实战

import requests  #请求网页数据

from bs4  import BeautifulSoup  #美味汤解析数据

import pandas  as pd

import time

from tqdm  import trange  #获取爬取速度

def get_bilibili_url (start, end) :

url_list = []

date_list = [i  forin pd.date_range(start, end).strftime( '%Y-%m-%d' )]

for date  in date_list:

url =  f"https://api.bilibili.com/x/v2/dm/history?type=1&oid=141367679&date= {date} "

url_list.append(url)

return url_list

def get_bilibili_danmu (url_list) :

headers = {

"user-agent""Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36" ,

"cookie""你自己的" #Headers中copy即可

}

file = open( "bilibili_danmu.txt"'w' )

forin trange(len(url_list)):

url = url_list[i]

response = requests.get(url, headers=headers)

response.encoding =  'utf-8'

soup = BeautifulSoup(response.text)

data = soup.find_all( "d" )

danmu = [data[i].text  forin range(len(data))]

for items  in danmu:

file.write(items)

file.write( "\n" )

time.sleep( 3 )

file.close()

if __name__ ==  "__main__" :

start =  '9/24/2020' #设置爬取弹幕的起始日

end =  '9/26/2020' #设置爬取弹幕的终止日

url_list = get_bilibili_url(start, end)

get_bilibili_danmu(url_list)

print(

"弹幕爬取完成"

)

3.数据预览

UnMvUjq.png!mobile

二、腾讯视频弹幕

1.网页分析

本文以爬取《脱口秀大会 第3季》最后一期视频弹幕为例,首先通过以下步骤找到存放弹幕的真实url。

Yb2IVbV.png!mobile

通过删减各参数,发现仅有timestamp参数的变化会影响弹幕数据的爬取,且timestamp参数是首项为15,公差为30的等差数列。可以大胆猜测腾讯视频每30秒更新一页弹幕数据,该视频长度为12399秒。而数据格式为标准的json格式,因此json.loads直接解析数据即可。

2.爬虫实战

import requests

import json

import time

import pandas  as pd

df = pd.DataFrame()

for page  in range( 151239930 ):

headers = { 'User-Agent''Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36' }

url =  'https://mfm.video.qq.com/danmu?otype=json&timestamp={}&target_id=5938032297%26vid%3Dx0034hxucmw&count=80' .format(page)

print( "正在提取第" + str(page) +  "页" )

html = requests.get(url,headers = headers)

bs = json.loads(html.text,strict =  False )   #strict参数解决部分内容json格式解析报错

time.sleep( 1 )

#遍历获取目标字段

forin bs[ 'comments' ]:

content = i[ 'content' ]   #弹幕

upcount = i[ 'upcount' ]   #点赞数

user_degree =i[ 'uservip_degree'#会员等级

timepoint = i[ 'timepoint' ]   #发布时间

comment_id = i[ 'commentid' ]   #弹幕id

cache = pd.DataFrame({ '弹幕' :[content], '会员等级' :[user_degree],

'发布时间' :[timepoint], '弹幕点赞' :[upcount], '弹幕id' :[comment_id]})

df = pd.concat([df,cache])

df.to_csv( 'tengxun_danmu.csv' ,encoding =  'utf-8' )

print(df.shape)

3.数据预览

miyMvmI.png!mobile

三、芒果TV弹幕

1.网页分析

本文以爬取《乘风破浪的姐姐》最后一期视频弹幕为例,首先通过以下步骤找到存放弹幕的真实url。

VZrAniz.png!mobile

通过分析参数,我们可以发现,芒果TV会生成首项为0,公差为1的等差数列json弹幕文件,每个json文件存储前一分钟内所有的弹幕数据。弹幕数据存放格式为json,数据解析较为简单。

2.爬虫实战

import requests

import json

import pandas  as pd

def get_mangguo_danmu (num1, num2, page) :

try :

url =  'https://bullet-ws.hitv.com/bullet/2020/09/29/{}/{}/{}.json'

print( "正在爬取第" + str(page) +  "页" )

danmuurl = url.format(num1, num2, page)

res = requests.get(danmuurl)

res.encoding =  'utf-8'

#print(res.text)

data = json.loads(res.text)

except :

print( "无法连接" )

details = []

forin range(len(data[ 'data' ][ 'items' ])):   # 弹幕数据在json文件'data'的'items'中

result = {}

result[ 'stype' ] = num2   # 通过stype可识别期数

result[ 'id' ] = data[ 'data' ][ 'items' ][i][ 'id' ]   # 获取id

try :   # 尝试获取uname

result[ 'uname' ] = data[ 'data' ][ 'items' ][i][ 'uname' ]

except :

result[ 'uname' ] =  ''

result[ 'content' ] = data[ 'data' ][ 'items' ][i][ 'content' ]   # 获取弹幕内容

result[ 'time' ] = data[ 'data' ][ 'items' ][i][ 'time' ]   # 获取弹幕发布时间

try :   # 尝试获取弹幕点赞数

result[ 'v2_up_count' ] = data[ 'data' ][ 'items' ][i][ 'v2_up_count' ]

except :

result[ 'v2_up_count' ] =  ''

details.append(result)

return details

#输入关键信息

def count_danmu () :

danmu_total = []

num1 = input( '第一个数字' )

num2 = input( '第二个数字' )

page = int(input( '输入总时长' ))

forin range(page):

danmu_total.extend(get_mangguo_danmu(num1, num2, i))

return danmu_total

def main () :

df = pd.DataFrame(count_danmu())

df.to_csv( 'mangguo_danmu.csv' )

if __name__ ==  '__main__' :

main()

3.数据预览

EZjqMzy.png!mobile

四、爱奇艺弹幕

1.网页分析

本文以爬取《乐队的夏天第2季》第13期上视频弹幕为例,首先通过以下步骤找到存放弹幕的真实url。

QzMBnyR.png!mobile

分析弹幕真实url,我们发现,参数5981449914376200是视频tvid,参数62是tvid倒数4为的前两位,参数00是tvid的最后两位,.z前的参数1为视频总时长除以300秒向上取整。观察相邻两个弹幕文件包,可以看出爱奇艺每5分钟更新一次弹幕文件。

3Mf2Y3.png!mobile

由于直接爬取出来的弹幕文件存在乱码,需要进行二进制编码,方可得到最终的弹幕数据。

2.爬虫实战

import zlib

import requests

# 1.爬取xml文件

def download_xml (url) :

bulletold = requests.get(url).content   # 二进制内容

return zipdecode(bulletold)

def zipdecode (bulletold) :

'对zip压缩的二进制内容解码成文本'

decode = zlib.decompress(bytearray(bulletold),  1532 ).decode( 'utf-8' )

return decode

forin range( 1 , 12 ):

# x是从1到12,12怎么来的,这一集总共57分钟,爱奇艺每5分钟会加载新的弹幕,57除以5向上取整

url =  'https://cmts.iqiyi.com/bullet/62/00/5981449914376200_300_' + str(x) +  '.z'

xml = download_xml(url)

# 把编码好的文件分别写入17个xml文件中(类似于txt文件),方便后边取数据

with open( './aiqiyi/iqiyi' + str(x) +  '.xml''a+' , encoding= 'utf-8'as f:

f.write(xml)

# 2.读取xml文件中的弹幕数据数据

from xml.dom.minidom  import parse

import xml.dom.minidom

def xml_parse (file_name) :

DOMTree = xml.dom.minidom.parse(file_name)

collection = DOMTree.documentElement

# 在集合中获取所有entry数据

entrys = collection.getElementsByTagName( "entry" )

print(entrys)

result = []

for entry  in entrys:

content = entry.getElementsByTagName( 'content' )[ 0 ]

print(content.childNodes[ 0 ].data)

i = content.childNodes[ 0 ].data

result.append(i)

return result

with open( "aiyiqi_danmu.txt" , mode= "w" , encoding= "utf-8"as f:

forin range( 1 , 12 ):

l = xml_parse( "./aiqiyi/iqiyi" + str(x) +  ".xml" )

for line  in l:

f.write(line)

f.write(

"\n"

3.数据预览

YZ3aQfA.png!mobile
欢迎关注「菜J学Python」,专注用Python爬虫、数据分析和可视化。如果您对本文感兴趣,可以点赞、在看和分享呀~

近期文章

Python网络爬虫与文本数据分析

rpy2库 | 在jupyter中调用R语言代码

tidytext | 耳目一新的R-style文本分析库

reticulate包 | 在Rmarkdown中调用Python代码

plydata库 | 数据操作管道操作符>>

七夕礼物 | 全网最火的钉子绕线图制作教程

读完本文你就了解什么是文本分析

文本分析在经管领域中的应用概述

综述:文本分析在市场营销研究中的应用

plotnine: Python版的ggplot2作图库

小案例: Pandas的apply方法   

stylecloud:简洁易用的词云库  

用Python绘制近20年地方财政收入变迁史视频   

Wow~70G上市公司定期报告数据集

漂亮~pandas可以无缝衔接Bokeh

YelpDaset: 酒店管理类数据集10+G

分享 ”和“ 在看 ”是更好的支持!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK