抖音与B站爬虫实战,获取核心数据

本文将深入讲解两大主流短视频平台(抖音、B站)的爬虫实战技术,提供可直接运行的代码解决方案,并分享突破反爬机制的核心技巧。


一、平台特性与爬虫难点对比

平台 数据价值 主要反爬措施 推荐抓取方式
抖音 视频数据、用户画像、热榜 签名验证、TLS指纹、滑块验证 Web接口+签名破解
B站 弹幕、评论、视频元数据 Referer校验、Cookie验证、频率限制 API接口+模拟登录

二、抖音爬虫实战:获取用户视频数据

核心原理:破解X-Bogus签名

抖音通过X-Bogus参数保护接口,需使用JavaScript逆向技术生成签名。

python

复制代码
import requests
import execjs  # 执行JS代码
import json

# 加载本地JS签名生成脚本(需提前保存)
with open('douyin_xbogus.js', 'r') as f:
    js_code = f.read()
ctx = execjs.compile(js_code)

def get_douyin_user_videos(user_id):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
        'Cookie': '你的抖音Cookie'  # 通过浏览器获取
    }
    
    # 构造原始URL
    base_url = f"https://www.douyin.com/aweme/v1/web/aweme/post/?device_platform=webapp&user_id={user_id}"
    
    # 通过JS生成X-Bogus签名
    xbogus = ctx.call('generateXbogus', base_url)
    signed_url = base_url + "&X-Bogus=" + xbogus
    
    try:
        response = requests.get(signed_url, headers=headers)
        data = response.json()
        
        # 解析视频数据
        videos = []
        for aweme in data['aweme_list']:
            video_info = {
                'id': aweme['aweme_id'],
                'desc': aweme['desc'],
                'create_time': aweme['create_time'],
                'duration': aweme['duration'] // 1000,  # 转为秒
                'likes': aweme['statistics']['digg_count'],
                'comments': aweme['statistics']['comment_count'],
                'url': aweme['video']['play_addr']['url_list'][0]
            }
            videos.append(video_info)
        return videos
    
    except Exception as e:
        print(f"抓取失败: {str(e)}")
        return []

# 使用示例
if __name__ == "__main__":
    user_id = "123456789"  # 替换为目标用户ID
    video_data = get_douyin_user_videos(user_id)
    print(f"获取到{len(video_data)}个视频")
    for video in video_data[:3]:
        print(video['desc'])
关键技术点:
  1. X-Bogus签名生成

    • 需要逆向抖音官方JavaScript生成算法

    • 使用PyExecJS执行JS代码生成有效签名

  2. 关键参数获取

    • user_id:通过分享链接获取(需URL解码)

    • Cookie:登录后从浏览器开发者工具获取

  3. 数据解析技巧

    • 视频真实地址在play_addr.url_list

    • 时间戳需要转换格式

注:完整X-Bogus生成JS代码需单独获取(因篇幅限制未展示)


三、B站爬虫实战:获取视频弹幕与评论

方案1:直接获取弹幕数据(无需登录)

python

复制代码
import requests
import re
import xml.etree.ElementTree as ET

def get_bilibili_danmaku(cid):
    """ 通过视频CID获取弹幕 """
    url = f"https://api.bilibili.com/x/v1/dm/list.so?oid={cid}"
    response = requests.get(url)
    response.encoding = 'utf-8'
    
    # 解析XML弹幕数据
    danmaku = []
    root = ET.fromstring(response.text)
    for d in root.findall('d'):
        attrs = d.attrib['p'].split(',')
        danmaku.append({
            'time': float(attrs[0]),
            'type': int(attrs[1]),
            'size': int(attrs[2]),
            'color': f"#{int(attrs[3]):06X}",
            'timestamp': int(attrs[4]),
            'text': d.text
        })
    return danmaku

# 使用示例
cid = "45678901"  # 通过视频API获取
danmaku_data = get_bilibili_danmaku(cid)
print(f"获取到{len(danmaku_data)}条弹幕")
方案2:获取视频评论(需模拟登录)

python

复制代码
import requests
import time
import random

def get_bilibili_comments(bvid):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
        'Referer': f'https://www.bilibili.com/video/{bvid}',
        'Cookie': '你的B站Cookie'
    }
    
    comments = []
    page = 1
    while True:
        url = f"https://api.bilibili.com/x/v2/reply?jsonp=jsonp&pn={page}&type=1&oid={get_aid(bvid)}&sort=2"
        
        try:
            response = requests.get(url, headers=headers)
            data = response.json()
            
            if data['code'] != 0:
                print(f"错误: {data['message']}")
                break
                
            # 解析评论数据
            for reply in data['data']['replies']:
                comments.append({
                    'user': reply['member']['uname'],
                    'content': reply['content']['message'],
                    'like': reply['like'],
                    'time': time.strftime("%Y-%m-%d %H:%M", time.localtime(reply['ctime']))
                })
            
            print(f"已获取第{page}页评论")
            page += 1
            
            # 随机延迟防止封禁
            time.sleep(random.uniform(1.5, 3))
            
            # 检查是否还有下一页
            if page > data['data']['page']['count'] // 20:
                break
                
        except Exception as e:
            print(f"抓取出错: {str(e)}")
            break
    
    return comments

def get_aid(bvid):
    """ 将BV号转换为AV号 """
    table = 'fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF'
    tr = {table[i]: i for i in range(58)}
    s = [11, 10, 3, 8, 4, 6]
    xor = 177451812
    add = 8728348608
    r = 0
    for i in range(6):
        r += tr[bvid[s[i]]] * 58 ** i
    return (r - add) ^ xor

# 使用示例
if __name__ == "__main__":
    bvid = "BV1gK4y1N7Jb"  # 替换为目标视频BV号
    comment_data = get_bilibili_comments(bvid)
    print(f"获取到{len(comment_data)}条评论")
关键技术点:
  1. CID/AID获取

    • 弹幕需要CID参数(通过视频API获取)

    • 评论需要AID(BV号需转换为AV号)

  2. 反爬突破技巧

    • 必须携带Referer请求头

    • Cookie需定期更新(有效期约1天)

    • 请求间隔需随机化(1-3秒)

  3. 数据解析

    • 弹幕为XML格式,属性包含位置/颜色/时间

    • 评论API返回分页JSON数据


四、高级反爬对抗方案

反爬类型 解决方案 工具推荐
签名验证 JavaScript逆向 PyExecJS/Frida
TLS指纹 修改客户端指纹 curl_cffi/requests_toolbelt
滑块验证 打码平台/OCR识别 ddddocr/第三方打码API
IP限制 代理IP轮换 快代理/站大爷

代理IP示例代码

python

复制代码
from itertools import cycle

proxies = cycle([
    'http://user:pass@192.168.1.1:8080',
    'http://user:pass@192.168.1.2:8080'
])

def make_request(url):
    proxy = next(proxies)
    try:
        return requests.get(url, proxies={"http": proxy}, timeout=10)
    except:
        return make_request(url)  # 自动切换下一个代理

五、法律合规边界

  1. 允许操作

    • 抓取公开视频信息(非隐私内容)

    • 个人学习研究目的

    • 遵守robots.txt限制

  2. 禁止行为

    • 破解付费内容

    • 抓取用户私信/手机号等隐私

    • 商业用途未经授权

    • 高频请求影响服务(>1次/秒)

建议:商业项目使用官方API(抖音开放平台/B站开放接口),个人学习控制请求频率


六、最佳实践建议

  1. 数据存储优化

    • 使用消息队列(RabbitMQ)缓冲请求

    • 分布式存储(MongoDB分片集群)

  2. 错误处理机制

    python

    复制代码
    # 重试装饰器示例
    from tenacity import retry, stop_after_attempt, wait_random
    
    @retry(stop=stop_after_attempt(3), wait=wait_random(min=2, max=5))
    def safe_request(url):
        response = requests.get(url)
        response.raise_for_status()
        return response
  3. 监控体系

    • 成功率监控(Prometheus)

    • 代理IP可用性检测

    • 自动切换签名算法版本

通过本指南,你可快速构建抖音/B站数据采集系统。随着平台反爬策略升级,需要持续关注接口变化并更新破解方案。建议优先考虑官方API方案,复杂场景可结合Selenium模拟真人操作。