Python3,多线程爬完B站UP主的视频弹幕及评论,我飘了~ ~ ~

2023-11-09

1、爬取视频弹幕信息

爬取视频的弹幕信息,同样要借助于我们的接口工具,这里我们使用Charles,获取到的弹幕的url地址

弹幕url

https://api.bilibili.com/x/v1/dm/list.so?oid={cid}

视频url

https://api.bilibili.com/x/player/pagelist?aid={aid}&jsonp=jsonp

至于怎么获取,我想大佬们都应该会的~ ~ 这里就不演示了,
接下来,老规矩,直接上代码:

get_video_barrage.py

# -*- coding: utf-8 -*-
"""
@ auth : carl_DJ
@ time : 2020-8-24
"""

def get_video_barrage(aid,uid,d):
	#获取视频弹幕信息
	cid = d['data']
	#弹幕地址,即运用到Charles抓取的接口地址
	barrage_url = 'https://api.bilibili.com/x/v1/dm/list.so?oid={cid}'
	#设置超时等待设置3秒
	r = get_http_session().get(barrage_url,timeout=3)
	#弹幕保存路径,及格式为 xml, 
	#uid类型要是 str的,不能是int类型,否则报错
	uid_dir_path = os.path.join(dir_path,str(uid))
	if not os.path.exists(uid_dir_path):
		os.makedirs(uid_dir_path)
		#设置弹幕信息保存路径
	barrage_path = os.path.join(uid_dir_path,f'barrage_{aid}.xml')
	#设置字符类型
	r.encoding = 'utf-8'
	content = t.text
	#保存弹幕信息
	save_file(barrage_path,content)
	print(f'video id:{aid} barrage save success !')

def get_up_video_info(name,id,filepath):
	#获取UP主的视频信息
	#读取文件信息
	res = read_json(filepath)
	#读取html页面中的vlist信息
	vlist = res['data']['list']['vlist']
	#循环读取vlist里面的内容
	for v in vlist:
		aid = v['aid']
		url = 'https://api.bilibili.com/x/player/pagelist?aid={aid}&jsonp=jsonp'
		player = get_http_session().get(url,timeout=3)
		#转换成json格式
		player = player.json()
		data = player['data']
		#如果没有数据,则直接返回
		if not data:
			return
		#循环读取data的内容
		for d in data:
			try:
				#这里直接调用上面写好的 get_video_barrage方法
				get_video_barrage(aid,uid,d)
			except Exception as e:
				#如果出错,则输出到get_up_video_info.log这个日志文件中
				log(traceback.format_exc(), 'error', 'get_up_video_info.log')
				error_str = f'name: [{name}], uid: [{uid}]'
				log(error_str,'error','get_up_video_info.log')
				

这里说明一下:
我直接写的是获取视频弹幕的方法!

2、爬取视频评论信息

关乎于获取评论的信息代码,和获取视频弹幕的方法一样
我就直接上代码,不做过多的啰嗦!

get_video_comment.py

# -*- coding: utf-8 -*-
"""
@ auth : carl_DJ
@ time : 2020-8-24
"""

def get_video_comment(uid,aid):
	#获取视频评论的信息
	comment_url = f'视频评论url'
	r = get_http_session().get(comment_url,timeout=3)
	#如果返回的状态码是200,则执行以下动作
	if r.status_code == 200:
		#同样这里uid要设置成str类型
		uid_dir_path = os.path.join(dir_path,str(uid))
		#如果没有地址,则创建
		if not os.path.exists(uid_dir_path):
			os.makedirs(uid_dir_path)
		common_path = os.path.join(uid_dir_path,f'comment_{aid}.json')
		#格式为json,缩进4个,内容不进行编码
		content = json.dumps(r.json(),indent=4,ensure_ascii= False)
		#保存
		save_file(common_path,content)
		#打印结果
		print(f'video id:{aid} comment save success')
		

代码到这里,就完成,没有什么难度,
那么接下来,我们就要使用线程,进行提速了

3、整合代码,线程提速~

同样,在爬取B站UP主的信息是,如果对单一视频进行爬取,还好一些
如果同时对100+UP主进行视频弹幕,评论进行爬取,那爬取量可海了去了~
而且还有可能在爬取一小半的时候,就被B站给反爬了,这是不是就尴尬了~
为了解决这种问题,我们必须要提速…
把省下来的时间,看看漫画,看看小视频,不香吗! !

说正就整,老规矩,上代码:

# -*- coding: utf-8 -*-
"""
@ auth : carl_DJ
@ time : 2020-8-24
"""


import os
import json
import requests
import traceback
import time

from threading import Thread
from concurrent.futures import ThreadPoolExecutor
from queue import Queue

#创建线程池: 10 个
executor = ThreadPoolExecutor(10)
queue = Queue()

#存放数据的根目录
dir_path = os.path.join('Bili_UP')

def get_http_session(pool_connections = 2,pool_maxsize=10,max_retries = 3)
    """
    http的连接池
    :param pool_connection: 连接池数
    :param poll_maxsize: 最大连接池数
    :param max_retries: 最大重试数
    :return:
    """
	session = requests.session()
	#适配器,传入3个参数
	adapter = requests.adapters.HTTPAdapter(pool_connections=pool_connections, pool_maxsize=pool_maxsize, max_retries=max_retries)
    session.mount('http://',adapter)
	session.mount('https://',adapter)
	return session

def save_file(filepath,content):
	'''
	由于这里保存的代码在《[Pyhotn3,爬取B站up主的信息!》已经写过过,
	这就就不在重复定义,不太熟练的,可以点击传送。
	'''
	# 保存文件
	pass   
def log(content,level,filepath):
	#创建错误日志级别
	pass

def make_dir(name):
	#创建dir
    pass
    
def read_json(filepath):
    """
    :param filepath: 读取文件
    :return:
    """
    #这里如果不写encoding='utf-8',转义会有问题
    with open(filepath,'r',encoding='UTF-8') as f:
        res = f.read()
        #将读取的文件转换成json格式,
        return json.loads(res)

def get_up_base_info(name, uid):
	#获取UP主的基本信息
	try:
		url = f'UP主的url地址'
		#设置超时等待设置3秒
		r = get_http_session().get(url, timeout=100)
		#如果返回的状态码是200,则执行以下动作
		if r.status.code ==200:
			up_dir = make_dir(name)
			filepath = os.path.join(up_dir,f'{uid}_base_info.json')
			content = json.dumps(r.json(), indent=4, ensure_ascii=False)
			#保存
			save_file(filepath, content)
			#打印信息
			print(f'{name} up主信息保存成功')
			#将信息推到队列中
			global queue
			queue.put((name,uid,filepath))
		else:
			fail_str = f'name: [{name}], uid: [{uid}], url: [{url}]'
			log(fail_str,'fail','base_info_fail.log')
	except Exception as e:
		log(traceback.format_exc(),'error','base_info_error.log')
		error_str = f'name: [{name}], uid: [{uid}]'
		log(error_str, 'error', 'base_info_error.log')

def get_video_barrage(aid,uid,d):
	#获取视频弹幕信息
	cid = d['data']
	#弹幕地址,即运用到Charles抓取的接口地址
	barrage_url = 'https://api.bilibili.com/x/v1/dm/list.so?oid={cid}'
	#设置超时等待设置3秒
	r = get_http_session().get(barrage_url,timeout=3)
	#弹幕保存路径,及格式为 xml, 
	#uid类型要是 str的,不能是int类型,否则报错
	uid_dir_path = os.path.join(dir_path,str(uid))
	if not os.path.exists(uid_dir_path):
		os.makedirs(uid_dir_path)
		#设置弹幕信息保存路径
	barrage_path = os.path.join(uid_dir_path,f'barrage_{aid}.xml')
	#设置字符类型
	r.encoding = 'utf-8'
	content = t.text
	#保存弹幕信息
	save_file(barrage_path,content)
	print(f'video id:{aid} barrage save success !')

def get_up_video_info(name,id,filepath):
	#获取UP主的视频信息
	#读取文件信息
	res = read_json(filepath)
	#读取html页面中的vlist信息
	vlist = res['data']['list']['vlist']
	#循环读取vlist里面的内容
	for v in vlist:
		aid = v['aid']
		url = 'https://api.bilibili.com/x/player/pagelist?aid={aid}&jsonp=jsonp'
		player = get_http_session().get(url,timeout=3)
		#转换成json格式
		player = player.json()
		data = player['data']
		#如果没有数据,则直接返回
		if not data:
			return
		#循环读取data的内容
		for d in data:
			try:
				#这里直接调用上面写好的 get_video_barrage方法
				get_video_barrage(aid,uid,d)
			except Exception as e:
				#如果出错,则输出到get_up_video_info.log这个日志文件中
				log(traceback.format_exc(), 'error', 'get_up_video_info.log')
				error_str = f'name: [{name}], uid: [{uid}]'
				log(error_str,'error','get_up_video_info.log')

def get_video_comment(uid,aid):
	#获取视频评论的信息
	comment_url = f'视频评论url'
	r = get_http_session().get(comment_url,timeout=3)
	#如果返回的状态码是200,则执行以下动作
	if r.status_code == 200:
		#同样这里uid要设置成str类型
		uid_dir_path = os.path.join(dir_path,str(uid))
		#如果没有地址,则创建
		if not os.path.exists(uid_dir_path):
			os.makedirs(uid_dir_path)
		common_path = os.path.join(uid_dir_path,f'comment_{aid}.json')
		#格式为json,缩进4个,内容不进行编码
		content = json.dumps(r.json(),indent=4,ensure_ascii= False)
		#保存
		save_file(common_path,content)
		#打印结果
		print(f'video id:{aid} comment save success')

def base_info_task(power_json):
	#设定启动方法,启动获取UP主的信息
	for d in power_json:
        uid = d['uid']
        name = d['name']
        #通过线程池去执行
        executor.submit(get_up_base_info,name,uid)
        
def get_video_task(power_json):
	#设定启动方法,启动获取UP主的视频和弹幕的信息
	#设定最大为10
	with ThreadPoolExecutor(max_workers = 10) as executor:
		#做循环,
		while True:
			global queue:
			name,uid,filepath = queue.get()
			executor.submit(get_up_video_info,name,uid,filepath)
			queue.task_done()
			#设置等待时间,防止被反爬
			time.sleep(2)

def mian():
	#读取up主的基本信息,
	power_json = read_json('UP_base.json')
	#启动线程
	Thread(target = base_info_task,args = (power_json, )).start()
	Thread(target=video_info_task).start()

if __name__ == '__main__':
    main()


注:
1.这里省略了make_dirlog等方法,
→① 是因为在《Pyhotn3,爬取B站up主的信息!》写过了
→②这篇主要是多线程爬取UP主的视频弹幕及评论,写的太多,容易造成混乱;
2.如果只想获取某一UP主的弹幕信息,可以把这里面的代码抽离出来,做单独爬取即可;
3.由于我们爬取的内容,是公开信息,所以,在爬取的过程中,B站并没有设置太多障碍!
4.如果要爬取的内容过多,小鱼还是建议以下几点:
→①设置User-Agent
→②设置 IP代理池
→③找别人给你爬

要是被封号,你就当吃瓜群众好了,O(∩_∩)O~

最后的最后

欢迎更多爬友来交流
同时,也给小鱼提更多更好的建议~~
让我们一起快乐,一起爬 !!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python3,多线程爬完B站UP主的视频弹幕及评论,我飘了~ ~ ~ 的相关文章

随机推荐

  • 一个完整的产品设计都要哪些设计流程

    设计理念是抽象的 它描述了一个产品从概念到完成的一般过程 然而 真正的产品设计过程要复杂得多 也要具体得多 因此 我们将分解这个过程中最重要的部分 并给实践中使用的建议 1 设计前期 通常 设计过程的第一步在产品设计之前就已经开始了 这是因
  • 如何利用数组实现高精度算法

    目录 引言 原理介绍 数据的输入 数字对齐的格式 以加法为例 小细节tips 代码如下 代码分析与书写过程 第一段 书写结构体 第二段 将字符串转化为数字输入数组 第三段 进行高精度数据的运算 以加法为例 最后一步 输出 引言 在C C 语
  • 分区容错性是什么意思_一篇文章搞清楚什么是分布式系统 CAP 定理

    专注于Java领域优质技术号 欢迎关注 来自 小旋锋 CAP定理是分布系统中的一个基本定理 它指出任何分布系统最多可以具有以下三个属性中的两个 一致性 Consistency 可用性 Availability 分区容错性 Partition
  • 充电IC驱动调试----移植充电IC bq25601

    关键词 MTK android 充电IC 内核 linux3 18 系统 android7 0 作者 arunboy 欢迎转载 请注明作者 在原有展讯平台下面的bq25601的基础上编写mtk平台下的bq25601代码 参考mtk平台下的
  • JAVA IDEA集成geotools gt-mif gdal读取.MIF

    JAVA IDEA集成geotools gt mif gdal读取 MIF 1 结论 2 问题1 gdal maven下载不下来 3 geotools gt mif maven配置 4 源码 5 运行结果 1 结论 gdal maven可以
  • ERR_PNPM_PEER_DEP_ISSUES Unmet peer dependencies

    ERR PNPM PEER DEP ISSUES 错误 两种解决方式 解决方式 方式一 忽略错误 项目根目录下 npmrc 中添加 strict peer dependencies false 方式二 自动安装对等依赖 项目根目录下 npm
  • 从实战中学前端:html+css 实现漂亮的按钮

    按钮初体验 html 表示中作为按钮的标签有 button 和 input
  • 产品经理的brd/prd/mrd的写法

    第一 撰写文档的工具 1 Excel 产品经理的神器 数据统计 数据报表 数据分析 数据图列制作 进度控制 2 PowerPoint 演示 3 Word 文档 4 Microsofo visio 2013 流程图 信息结构图 5 Axure
  • js计算两个时间相差月份

    约束 结束时间endTime gt 开始时间startTime 思路 之前总是会遗漏掉很多种情况 所以列举出各种情况 发现其规律 1 年 月 endTime getYear startTime getYear 12 2 月 月 endTim
  • 题目45 检查数组中是否存在满足规则的数组组合1(ok)

    给定一个正整数数组 检查数组中是否存在满足规则的数组组合 规则 A B 2C 输入描述 第一行输出数组的元素个数 接下来一行输出所有数组元素 用空格隔开 输出描述 如果存在满足要求的数 在同一行里依次输出 规则里 A B C的取值 用空格隔
  • iframe的父与子窗体之间的传值(IE与FF都可以用)

    请看下面简单例子 不多解释 父窗体 test htm
  • 用花生壳内网穿透实现外网访问内网SQL数据库

    内网穿透实现外网访问内网SQL数据库 温斯坦丁 陈的博客 CSDN博客
  • Hive启动

    1 查看hdfs启动没 start dfs sh 2 查看yarn启动没 start yarn sh 3 查看MySQL启动没 1 service mysqld start 2 mysql uroot p 作者机器密码 hadoop 和hi
  • 02趣味算法 --- 算法复杂性

    14天阅读挑战赛努力是为了不平庸 算法学习有些时候是枯燥的 这一次 让我们先人一步 趣学算法 欢迎记录下你的那些努力时刻 算法学习知识点 算法题解 遇到的算法bug 等等 在分享的同时加深对于算法的理解 同时吸收他人的奇思妙想 一起见证技术
  • 常用分析问题的几种方法

    文章目录 1 5W2H分析法 2 麦肯锡问题解决框架 3 SWOT分析法 4 SMART 1 5W2H分析法 5W2H指的就是7个英文单词 是二战中美国陆军兵器修理部首创 对于决策和执行性的活动措施也非常有帮助 很适合在做项目之前通过这个模
  • spring事务出现的超卖问题

    问题分析 我的代码逻辑如下 Override Transactional isolation Isolation REPEATABLE READ propagation Propagation REQUIRED public synchro
  • C语言数据存储与数据打印的奥秘

    尊师 https blog csdn net yyywill 数据存储 要记住 在计算机中 数据都是以 二进制 来存储的 十六进制 八进制和十进制只是我们人为定义的一种表现形式 数据打印 谈到数据打印 有人可能会说 不就是 printf 吗
  • leetcode精选

    7 LeetCode题目精选 7 1 两数之和 问题链接 https leetcode cn com problems two sum 7 1 1 问题描述 给定一个整数数组 nums 和一个目标值 target 请你在该数组中找出和为目标
  • MySQL 读写分离 使用驱动com.mysql.jdbc.ReplicationDriver

    说明文档 http dev mysql com doc refman 5 1 en connector j reference replication connection html 代码例子 1 import java sql Conne
  • Python3,多线程爬完B站UP主的视频弹幕及评论,我飘了~ ~ ~

    利用线程爬取B站Up主弹幕及评论 1 爬取视频弹幕信息 2 爬取视频评论信息 3 整合代码 线程提速 1 爬取视频弹幕信息 爬取视频的弹幕信息 同样要借助于我们的接口工具 这里我们使用Charles 获取到的弹幕的url地址 弹幕url h