目錄
背景
前幾天看了隱祕的角落,覺得這劇真心不錯,於是乎就像看看大家是否和我的看法一致,找了一圈沒找到完整的爬蟲代碼,都藏着掖着的幹啥啊,能恰飯嗎!!!算了,利用他們提供的部分信息自己寫一個吧。
爬蟲分析
傻瓜式分析
打開一看,彈幕的格式是固定在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 吶啦。