Python爬虫-爱奇艺弹幕实战-隐秘的角落-2020最新

目录

背景

爬虫分析

傻瓜式分析

进阶式分析

实战代码

结果展示

数据分析

中文弹幕情感分析


背景

前几天看了隐秘的角落,觉得这剧真心不错,于是乎就像看看大家是否和我的看法一致,找了一圈没找到完整的爬虫代码,都藏着掖着的干啥啊,能恰饭吗!!!算了,利用他们提供的部分信息自己写一个吧。

爬虫分析

傻瓜式分析

打开一看,弹幕的格式是固定在DIV里面的,但是会实时更新,所以傻瓜式的操作别想了。

那咋办,小神童的我能放弃么? Ctrl+Shift+C 直接打开审查面板,切换到Network界面 ,Ctrl+R刷新一下,响应请求就开始了。

进阶式分析

根据残缺不全的指引,搜索了bullet(弹幕的英文翻译),诶嘿,一个标识映入眼帘,多打开几个看看,对比对比有没有啥规律,巧了,还真的有。

初步判断完毕,一复制该网址就会下载一个压缩包,压缩包里面就是弹幕,下面我只要把每集的弹幕压缩包都下载下来就行!!!这里还有两个问题

  • 第一尝试直接下载解压压缩包是不行的,需要解析,这里详见StackFlow解决办法
  • 既然要分集数爬取,自然要判断每个集数的id,上面初步判断电视剧id标错了,真实的电视剧id是albumid,直接在面板搜索albumid进行查找,果然有这个东西。

傻瓜式复制到新窗口里看看是不是(这里就是凭借着我聪慧的小脑瓜判断),拿到json格式数据基本就可以宣告胜利了。

万事具备,只欠东风,一个字,干!!!

实战代码

#!/usr/bin/env python

# -*- encoding: utf-8 -*-

'''
@Author  :   {Jack Zhao}

@Time    :   2020/6/29 10:39

@Contact :   {[email protected]}

@Desc    :  隐秘的角落弹幕爬取复现
'''
import json
import zlib

import pandas as pd
import requests
from bs4 import BeautifulSoup
from threading import Thread

def get_IQ_data(tv_index,tv_id):
	'''由上文分析可知,只需要知道tvid,即可下载对应的弹幕压缩包'''
	url = 'https://cmts.iqiyi.com/bullet/{}/{}/{}_300_{}.z'
	datas = pd.DataFrame(columns=['uid','contentsId','contents','likeCount'])
	for index in range(1,20):
		# 这里每一集的时长所对应的弹幕有好多个压缩包,为压缩包连续编号,最好从头看到尾,这里我没耐心看盲猜小于20个
		# 后分析发现,弹幕文件每5分钟(300秒)向服务器请求一次,故每集弹幕文件数量等于视频时间除以300之后向上取整,实际编程时这里可以简单处理
		myUrl = url.format(tv_id[-4:-2],tv_id[-2:],tv_id,index)
		# print(myUrl)
		res = requests.get(myUrl)
		if res.status_code == 200:
			btArr = bytearray(res.content) # 需要解码
			xml = zlib.decompress(btArr).decode('utf-8')
			bs = BeautifulSoup(xml,"xml") # 解析xml文档
			data = pd.DataFrame(columns=['uid','contentsId','contents','likeCount'])
			data['uid'] = [i.text for i in bs.findAll('uid')]  # 用户编号
			data['contentsId'] = [i.text for i in bs.findAll('contentId')] # 弹幕对应ID
			data['contents'] = [i.text for i in bs.findAll('content')] # 内容
			data['likeCount'] = [i.text for i in bs.findAll('likeCount')] # 他人点赞该弹幕的数量
		else:
			break
		datas = pd.concat([datas,data],ignore_index = True) # 一集中所有弹幕数据录入一个df,不设置ignore的话会出现index重复
	datas['tv_name'] = str(tv_index) # 增加一列作为集数标识
	return datas


def get_TV_Id(aid):
	'''每一集的tvid其实是由albumid生成的,具体Find - album找到info即可'''
	tv_id_list = []
	for page in range(1,2):
		url = 'https://pcw-api.iqiyi.com/albums/album/avlistinfo?aid=' \
              + aid + '&page='\
              + str(page) + '&size=30'
		res = requests.get(url).text
		res_json = json.loads(res)
		# 视频列表
		movie_list = res_json['data']['epsodelist']
		for j in movie_list:
			tv_id_list.append(j['tvId'])
		return tv_id_list

if __name__ == '__main__':
	# album id
	my_aid = '252449101'
	my_tv_id_list = get_TV_Id(my_aid) # 获得电视剧集数
	print("下面是TV_ID列表:")
	print(my_tv_id_list)
	data_all = pd.DataFrame(columns=['uid', 'contentsId', 'contents', 'likeCount','tv_name']) # 同样设置一个总表作为产出
	for index,i in enumerate(my_tv_id_list):
		#data = get_data('隐秘的角落第'+index+'集',str(i))
		# 下一步可Thread改造成多进程
		data = pd.DataFrame(get_IQ_data(index, str(i)))
		data.to_csv('./'+str(index+1)+'.csv')
		data_all = pd.concat([data_all, data], ignore_index=True)  # 存入总表
	print("12集弹幕已经存入csv文件中")
	data_all.to_csv('data_all.csv')
	print('总表已经合并完成,已存为csv')





结果展示

多线程操作很简单的,详见多线程教学

最后的数据大概有20w条左右吧,等有时间再用Pyecharts分析分析,顺便复习一下基操,see you 呐啦。

数据分析

中文弹幕情感分析

# 下面采取的是Notebook开发
# 复习一下知识点,读入数据库
import pymysql
import pandas as pd 
# 创建连接
connection = pymysql.connect(host='localhost',port=3306,user='root',password='chuan32',db='zc')
cursor =connection.cursor() # 获取游标
# 创建数据表,一般使用navicate直接构造表结构,不使用代码
# 下面从csv中读出数据并存入数据库
content = pd.DataFrame(pd.read_csv('data_all.csv'))
print(content.head(5))
# 由于爬虫书写的失误,tv_name一列需要加一
content['tv_name'] = content['tv_name']+1 
content.iloc[:,1:] # 查看内容
content.iloc[:,1:]
uid = content['uid'].astype(str)
contentsId = content['contentsId'].astype(str)
contents = content['contents'].astype(str)
likeCount = content['likeCount'].astype(str)
tv_name = content['tv_name'].astype(str)
content.iloc[:,1:]
# 下面存入数据库
cursor = connection.cursor()
sql = 'insert into iqiyi(uid,contentsId,contents,likeCount,tv_name) values (%s,%s,%s,%s,%s);'
for i in range(len(content)):
    try:
        cursor.execute(sql,[uid[i],contentsId[i],contents[i],likeCount[i],tv_name[i]])  
        connection.commit()
    except Exception as e:
        print(e)
        conn.rollback()
# 保证事务一致性和及时关闭
cursor.close()
connection.close()
# 数据库查询
# 由于上面已经关闭连接,这里许哟啊重新进行连接
config = {'host':'localhost','port':3306,'user':'root','password':'chuang199832','db':'zc'}
conn = pymysql.connect(**config)
cursor = conn.cursor()
sql = 'select * from iqiyi;'
cursor.execute(sql)
data = cursor.fetchall()
print(len(data))
print(type(data))
# 获取表头
decs = []
for field in cursor.description:
    decs.append(field[0])
print(decs)
# 转化为DataFrame
data = pd.DataFrame(data,columns= dec)
data.head(5)
# 采用snowNLP进行情感分析
from snownlp import SnowNLP
print(data.head(5))
data_copy = data.copy() # 操作前最好先存一个副本
senti = []
for index,content in enumerate(data_copy['contents']):
    content = SnowNLP(content)# 创建分析对象
    senti.append(content.sentiments)

data_copy['sentiment'] = senti
data_copy

猜你喜欢

转载自blog.csdn.net/weixin_40539952/article/details/107018666
今日推荐