用 Python 抓取 bilibili 弹幕并分析!

01 实现思路

首先,利用哔哩哔哩的弹幕接口,把数据保存到本地。接着,对数据进行分词。最后,做了评论的可视化。

02 弹幕数据

平常我们在看视频时,弹幕是出现在视频上的。实际上在网页中,弹幕是被隐藏在源代码中,以XML的数据格式进行加载的。

比如:

https://comment.bilibili.com/123072475.xml

一个固定的url地址 + 视频的cid + .xml

只要找到你想要的视频cid,替换这个url就可以爬取所有弹幕了(b站大部分网页给出的字幕限制是1000条)。

一个视频的cid在哪里呢?

右键网页,打开网页源代码,搜索 "cid": 就能找到:

03 保存数据到本地

有了数据的接口链接,我们就可以利用request模块,获取数据了。

然后,再利用xpath简单的解析xml,就可以把所有的弹幕信息汇总到一个列表里了。最后,把列表转化成dataframe,保存到本地。

# 许嵩新歌《雨幕》
# bilibili视频弹幕文件
url = 'https://comment.bilibili.com/123072475.xml'

# 发送请求
response = requests.get(url)
xml = etree.fromstring(response.content)

# 解析数据
dm = xml.xpath("/i/d/text()")
print(dm)  # list

# 把列表转换成 dataframe
dm_df = pd.DataFrame(dm, columns=['弹幕内容'])
print(dm_df)

# 存到本地
# 解决了中文乱码问题
dm_df.to_csv('雨幕-弹幕.csv', encoding='utf_8_sig')

保存的csv数据:

04 对数据进行分词

制作词云前,需要把弹幕数据进行分词。

关于jieba分词,可以参考:

https://blog.csdn.net/dnxbjyj/article/details/72854460

# jieba分词
dm_str = " ".join(dm)
words_list = jieba.lcut(dm_str)  # 切分的是字符串,返回的是列表
words_str = " ".join(words_list)

05 词云可视化

通过创建词云对象、设置词云参数,最终生成图片,保存到本地。

# 读取本地文件
backgroud_Image = plt.imread('1.jpg')

# 创建词云
wc = WordCloud(
    background_color='white',
    mask=backgroud_Image,
    font_path='./SourceHanSerifCN-Medium.otf',  # 设置本地字体

    max_words=2000,
    max_font_size=100,
    min_font_size=10,
    color_func=random_color_func,
    random_state=50,
)

word_cloud = wc.generate(words_str) # 产生词云
word_cloud.to_file("yumu.jpg") #保存图片

可以使用Dijkstra算法来求解不带权无向连通图中从顶点1到顶点4的一条最短路径。具体步骤如下: 1. 初始化距离数组dist,将所有顶点的距离初始化为无穷大,将起点1的距离设为0。 2. 创建一个空堆heap,将起点1加入堆中。 3. 当堆不为空时,取出堆顶元素u,遍历u的所有邻居v,如果从起点1到v的距离比dist[v]更短,则更新dist[v]的值,将v加入堆中。 4. 重复步骤3直到堆为空或者堆顶元素是终点4。 5. 如果dist[4]的值为无穷大,则表示从起点1无法到达终点4。否则,可以通过反向遍历记录路径,从终点4一直走到起点1,即可得到一条从1到4的最短路径。 以下是C语言实现示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <limits.h> #define N 5 int graph[N][N] = { {0, 1, 1, 0, 0}, {1, 0, 1, 1, 0}, {1, 1, 0, 1, 0}, {0, 1, 1, 0, 1}, {0, 0, 0, 1, 0} }; int dist[N]; int visited[N]; typedef struct { int vertex; int distance; } Node; Node heap[N]; int heap_size = 0; void swap(Node *a, Node *b) { Node temp = *a; *a = *b; *b = temp; } void push(Node node) { heap[heap_size++] = node; int i = heap_size - 1; while (i > 0) { int parent = (i - 1) / 2; if (heap[parent].distance > heap[i].distance) { swap(&heap[parent], &heap[i]); i = parent; } else { break; } } } Node pop() { Node result = heap[0]; heap[0] = heap[--heap_size]; int i = 0; while (i * 2 + 1 < heap_size) { int left = i * 2 + 1; int right = i * 2 + 2; int child = left; if (right < heap_size && heap[right].distance < heap[left].distance) { child = right; } if (heap[child].distance < heap[i].distance) { swap(&heap[child], &heap[i]); i = child; } else { break; } } return result; } void dijkstra(int start, int end) { for (int i = 0; i < N; i++) { dist[i] = INT_MAX; } dist[start] = 0; push((Node){start, 0}); while (heap_size > 0) { Node node = pop(); if (visited[node.vertex]) { continue; } visited[node.vertex] = 1; if (node.vertex == end) { return; } for (int i = 0; i < N; i++) { if (graph[node.vertex][i]) { int alt = dist[node.vertex] + 1; if (alt < dist[i]) { dist[i] = alt; push((Node){i, alt}); } } } } } int main() { dijkstra(0, 3); if (dist[3] == INT_MAX) { printf("No path from 1 to 4\n"); } else { printf("Shortest path from 1 to 4 is %d\n", dist[3]); } return 0; } ``` 这段代码会输出从顶点1到顶点4的最短路径长度。如果路径不存在,则会输出"No path from 1 to 4"。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值