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 吶啦。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章