您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# 怎么用Python获取爱奇艺电视剧弹幕数据
## 目录
1. [弹幕数据概述](#弹幕数据概述)
2. [技术原理分析](#技术原理分析)
3. [环境准备](#环境准备)
4. [网页结构分析](#网页结构分析)
5. [API接口逆向](#api接口逆向)
6. [请求参数解密](#请求参数解密)
7. [数据抓取实战](#数据抓取实战)
8. [数据存储方案](#数据存储方案)
9. [反爬对抗策略](#反爬对抗策略)
10. [数据分析应用](#数据分析应用)
11. [法律风险提示](#法律风险提示)
12. [完整代码示例](#完整代码示例)
## 弹幕数据概述
弹幕(Danmaku)是一种实时评论系统,起源于日本Niconico动画,现已成为中国视频平台的标配功能。爱奇艺作为国内领先的视频平台,其弹幕数据具有重要研究价值:
- **用户行为分析**:反映观众情绪波动和关注点
- **内容质量评估**:通过弹幕密度评估剧情高潮
- **社交互动研究**:观察用户间的互动模式
- **舆情监控**:捕捉热门话题和争议点
根据爱奇艺2022年财报显示,平台日均弹幕量超过1.2亿条,热门剧集单集弹幕可达50万+。
## 技术原理分析
爱奇艺弹幕系统采用典型的HTTP+WebSocket架构:
```mermaid
sequenceDiagram
用户->>客户端: 发送弹幕
客户端->>服务器: HTTP POST加密请求
服务器->>CDN: 分发弹幕数据
CDN->>客户端: WebSocket实时推送
数据获取主要有两种方式: 1. 实时抓取:通过WebSocket连接获取实时弹幕流 2. 历史抓取:从API接口获取已存储的弹幕数据
本文重点讲解历史弹幕获取方法。
# 推荐Python 3.8+
conda create -n iqiyi python=3.8
pip install requests pycryptodome pandas selenium
requests
:网络请求核心库pycryptodome
:AES/RC4等加密算法实现selenium
:用于动态渲染页面获取关键参数websocket-client
:实时弹幕获取备用import hashlib
import json
from Crypto.Cipher import AES
import time
import random
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Referer': 'https://www.iqiyi.com/'
}
https://cmts.iqiyi.com/bullet/[分段ID]_[时间戳].json
tvid
、vid
、key
需要动态获取// 页面源码中的关键JSON
window.Q.PageInfo.playPageInfo = {
"tvId": "1234567890",
"vid": "a1b2c3d4e5",
"duration": 3600
}
通过抓包分析发现主接口:
GET /bullet/55/00/55_300_5.zsv
Host: cmts.iqiyi.com
Params:
tvid: 1234567890
business: danmu
is_iqiyi: true
is_video_page: true
authkey: xxxxxxxx
/jp/video
接口获取def generate_authkey(tvid, timestamp):
secret = "8e4907c148d9477c5a6c545ce6e6e54b"
msg = f"{tvid}_{timestamp}".encode()
return hmac.new(secret.encode(), msg, hashlib.sha256).hexdigest()
爱奇艺使用多层加密策略: 1. 第一层:URL参数RC4加密 2. 第二层:响应数据AES-CBC解密 3. 第三层:数据包zlib压缩
def decrypt_data(encrypted_data, key):
iv = b'0102030405060708'
cipher = AES.new(key.encode(), AES.MODE_CBC, iv)
decrypted = cipher.decrypt(encrypted_data)
return unpad(decrypted, AES.block_size)
def parse_danmu(response):
# Step1: Base64解码
raw = base64.b64decode(response.text)
# Step2: zlib解压
decompressed = zlib.decompress(raw)
# Step3: AES解密
decrypted = decrypt_data(decompressed, 'xxxxxx')
return json.loads(decrypted)
根据视频时长自动计算分片:
def get_segments(duration):
segment_count = duration // 300 + 1
return [f"{i:02d}_{(i+1)*300}" for i in range(segment_count)]
def build_request(tvid, segment):
timestamp = int(time.time() * 1000)
url = f"https://cmts.iqiyi.com/bullet/{segment}.json"
params = {
"tvid": tvid,
"business": "danmu",
"authkey": generate_authkey(tvid, timestamp),
"timestamp": timestamp
}
return requests.get(url, params=params, headers=HEADERS)
try:
response = build_request(tvid, segment)
if response.status_code == 200:
return parse_danmu(response)
elif response.status_code == 403:
raise Exception("触发反爬机制")
except Exception as e:
logger.error(f"获取分片{segment}失败: {str(e)}")
格式 | 优点 | 缺点 |
---|---|---|
JSON | 结构清晰 | 占用空间大 |
CSV | 易处理 | 嵌套结构难表达 |
SQLite | 查询方便 | 需要数据库知识 |
from pymongo import MongoClient
client = MongoClient('mongodb://localhost:27017/')
db = client['iqiyi_danmu']
def save_to_mongo(data):
collection = db[data['tvid']]
result = collection.insert_many(data['comments'])
print(f"插入{len(result.inserted_ids)}条数据")
def clean_danmu(raw):
return {
"content": raw.get("content"),
"time": float(raw.get("showTime", 0)),
"color": int(raw.get("color", 16777215)),
"user": raw.get("uid")[:3] + "****",
"send_time": datetime.fromtimestamp(raw.get("time")/1000)
}
# 代理IP池实现
class ProxyPool:
def __init__(self):
self.proxies = []
self.current = 0
def get_proxy(self):
proxy = self.proxies[self.current]
self.current = (self.current + 1) % len(self.proxies)
return proxy
# 使用示例
pool = ProxyPool()
requests.get(url, proxies={"http": pool.get_proxy()})
import random
from time import sleep
def smart_sleep(last_request):
elapsed = time.time() - last_request
if elapsed < 1.5:
sleep(random.uniform(0.5, 2.5))
import matplotlib.pyplot as plt
def plot_danmu_distribution(data):
times = [d['time'] for d in data]
plt.hist(times, bins=50)
plt.title("弹幕时间分布")
plt.xlabel("视频时间(秒)")
plt.ylabel("弹幕数量")
plt.show()
# iqiyi_danmu_spider.py
import requests
import json
import hashlib
import hmac
import time
from urllib.parse import quote
class IqiyiDanmu:
def __init__(self, tvid):
self.tvid = tvid
self.base_url = "https://cmts.iqiyi.com/bullet"
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
'Referer': f'https://www.iqiyi.com/v_{tvid}.html'
}
def generate_sign(self, timestamp):
key = "xxxxxx".encode()
msg = f"{self.tvid}_{timestamp}".encode()
return hmac.new(key, msg, hashlib.sha256).hexdigest()
def get_segments(self, duration):
return [f"{i:02d}_{(i+1)*300}" for i in range(duration//300 +1)]
def fetch_segment(self, segment):
timestamp = int(time.time() * 1000)
params = {
"tvid": self.tvid,
"business": "danmu",
"sign": self.generate_sign(timestamp),
"timestamp": timestamp
}
url = f"{self.base_url}/{segment}.json"
try:
resp = requests.get(url, params=params, headers=self.headers)
return self.parse_response(resp)
except Exception as e:
print(f"Error fetching {segment}: {str(e)}")
return None
def parse_response(self, response):
if response.status_code != 200:
return None
try:
data = response.json()
return [{
'time': item.get('time'),
'content': item.get('content'),
'color': item.get('color')
} for item in data.get('data', [])]
except json.JSONDecodeError:
return None
if __name__ == "__main__":
spider = IqiyiDanmu("1234567890")
segments = spider.get_segments(3600) # 60分钟视频
all_danmu = []
for seg in segments:
if danmus := spider.fetch_segment(seg):
all_danmu.extend(danmus)
time.sleep(1.5)
with open("danmu.json", "w", encoding="utf-8") as f:
json.dump(all_danmu, f, ensure_ascii=False)
本文详细讲解了从爱奇艺获取弹幕数据的技术方案,包含以下关键点: 1. 逆向分析爱奇艺弹幕API接口 2. 处理复杂的加密参数体系 3. 实现稳定可持续的抓取流程 4. 数据存储与分析的基础方法
建议进一步研究的方向: - 结合OCR识别内嵌弹幕 - 开发实时弹幕分析系统 - 构建弹幕情感分析模型
注意事项:技术研究仅供参考,请遵守相关法律法规,合理控制抓取频率,避免对目标服务器造成压力。 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。