更多文章见个人博客
一、前期准备
- 爬取目标:【春晚鬼畜】赵本山:我就是念诗之王!【改革春风吹满地】评论区
- 所需要的模块
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 | 性别 | 等级 | 评论内容 | 点赞数 |
---|
- 对第一页的数据进行获取,得到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)#请求网页,获取数据
- 对获取到的数据进行分析筛选
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)#分析数据
- 将数据保存到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()
- 使用多线程爬取所有页面
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了,不过还好只被封了十分钟