【python爬虫】使用requests+多线程爬取B站改革春风吹满地视频5w评论

一、前期准备

from fake_useragent import UserAgent     #随机请求头
import requests     #请求网页
from requests.exceptions import RequestException    #请求异常处理
import csv    #将数据存储到Excel
from datetime import datetime    #时间转换
from multiprocessing.dummy import Pool as pl    #多线程

二、网页分析

在获取评论之前,首先要分析网页结构,寻找所需要的数据,网页中显示评论共为77674条评论,2385页。
在这里插入图片描述
之后通过Chrome开发者工具寻找加载评论来源
在这里插入图片描述
需要去掉链接中间的一些参数
最终发现加载评论链接为:

https://api.bilibili.com/x/v2/reply?pn=1&type=1&oid=19390801

访问链接后可发现所有评论是由json数据存储在网页中,链接中pn参数为页码,共有77706条评论(因为评论在一直增加),2385页,每页有20条评论(不包括楼层中的评论),本次主要爬取楼层评论,所以共有约2385*20=47700条评论。

三、数据获取

本代码爬取评论区8个数据,如下:

楼层 时间 用户昵称 ID 性别 等级 评论内容 点赞数
  1. 对第一页的数据进行获取,得到json格式数据
ua = UserAgent(verify_ssl=False)#忽略ssl验证
headers = {'User-Agent': ua.random}#构造随机请求头

def get_page(url,headers):
	try:
		response = requests.get(url,headers = headers)#请求网页
		if response.status_code == 200:
			return response.json()#如果状态码为200则返回json格式数据
		return None
	except RequestException:#否则返回none
		return None
		
def main(url):
	html_json = get_page(url,headers)#请求网页,获取数据
  1. 对获取到的数据进行分析筛选
def parse_page(html_json):
	n = html_json['data']['page']['size']#获取每页中的评论数,一般为20条
	for i in range(0,n):
		info = {
				'floor': html_json['data']['replies'][i]['floor'],#获取楼层信息
				'time': datetime.fromtimestamp(html_json['data']['replies'][i]['ctime']),#获取日期时间,因为B站的时间是用秒为单位的时间戳计时,需要转换
				'nickname': html_json['data']['replies'][i]['member']['uname'],#获取用户昵称
				'id': html_json['data']['replies'][i]['mid'],#获取用户ID
				'sex': html_json['data']['replies'][i]['member']['sex'],#获取用户性别
				'level': html_json['data']['replies'][i]['member']['level_info']['current_level'],#获取用户等级
				'content': html_json['data']['replies'][i]['content']['message'],#获取评论内容
				'like': html_json['data']['replies'][i]['like']#获取评论点赞数
		}
		
def main(url):
	html_json = get_page(url,headers)#请求网页,获取数据
	parse_page(html_json)#分析数据
  1. 将数据保存到csv文件中
def parse_page(html_json):
	n = html_json['data']['page']['size']#获取每页中的评论数,一般为20条
	for i in range(0,n):
		info = {
				'floor': html_json['data']['replies'][i]['floor'],#获取楼层信息
				'time': datetime.fromtimestamp(html_json['data']['replies'][i]['ctime']),#获取日期时间,因为B站的时间是用秒为单位的时间戳计时,需要转换
				'nickname': html_json['data']['replies'][i]['member']['uname'],#获取用户昵称
				'id': html_json['data']['replies'][i]['mid'],#获取用户ID
				'sex': html_json['data']['replies'][i]['member']['sex'],#获取用户性别
				'level': html_json['data']['replies'][i]['member']['level_info']['current_level'],#获取用户等级
				'content': html_json['data']['replies'][i]['content']['message'],#获取评论内容
				'like': html_json['data']['replies'][i]['like']#获取评论点赞数
		}
		write_file(info)#将信息保存

def write_file(info):
	with open('改革春风吹满地.csv','a',encoding='gb18030',newline='') as f:
		writer = csv.writer(f,dialect='excel')
		writer.writerow(info.values())#将获取到的信息保存到csv文件中
		f.close()
  1. 使用多线程爬取所有页面
if __name__ == '__main__':
	pool = pl(10)#开启4线程
	url = ['https://api.bilibili.com/x/v2/reply?&jsonp=jsonp&pn={}&type=1&oid=19390801&sort=0&_=1549711529949'.format(str(m)) for m in range(1,2408)]#所有链接
	pool.map(main,url)
	pool.close()
	pool.join()

四、完整代码

from fake_useragent import UserAgent
import requests
from requests.exceptions import RequestException
import csv
from datetime import datetime
from multiprocessing.dummy import Pool as pl

ua = UserAgent(verify_ssl=False)#忽略ssl验证
headers = {'User-Agent': ua.random}#构造随机请求头

def get_page(url,headers):
	try:
		response = requests.get(url,headers = headers)#请求网页
		if response.status_code == 200:
			return response.json()#如果状态码为200则返回json格式数据
		return None
	except RequestException:#否则返回none
		return None

def parse_page(html_json):
	n = html_json['data']['page']['size']#获取每页中的评论数,一般为20条
	for i in range(0,n):
		info = {
				'floor': html_json['data']['replies'][i]['floor'],#获取楼层信息
				'time': datetime.fromtimestamp(html_json['data']['replies'][i]['ctime']),#获取日期时间,因为B站的时间是用秒为单位的时间戳计时,需要转换
				'nickname': html_json['data']['replies'][i]['member']['uname'],#获取用户昵称
				'id': html_json['data']['replies'][i]['mid'],#获取用户ID
				'sex': html_json['data']['replies'][i]['member']['sex'],#获取用户性别
				'level': html_json['data']['replies'][i]['member']['level_info']['current_level'],#获取用户等级
				'content': html_json['data']['replies'][i]['content']['message'],#获取评论内容
				'like': html_json['data']['replies'][i]['like']#获取评论点赞数
		}
		write_file(info)#将信息保存

def write_file(info):
	with open('改革春风吹满地.csv','a',encoding='gb18030',newline='') as f:
		writer = csv.writer(f,dialect='excel')
		writer.writerow(info.values())#将获取到的信息保存到csv文件中
		f.close()
		
def main(url):
	html_json = get_page(url,headers)#请求网页,获取数据
	parse_page(html_json)#分析数据

if __name__ == '__main__':
	pool = pl(10)#开启4线程
	url = ['https://api.bilibili.com/x/v2/reply?&jsonp=jsonp&pn={}&type=1&oid=19390801&sort=0&_=1549711529949'.format(str(m)) for m in range(1,2408)]#所有链接
	pool.map(main,url)
	pool.close()
	pool.join()

ps:其实应该设置一些延时或使用多个IP,否则会被B站封IP,我第一次爬没问题,第二次爬了一点链接状态码就是403了,不过还好只被封了十分钟

发布了3 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43167980/article/details/86924176