You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tweepy抓取推文时无法获取单条推文全部媒体文件问题求解

问题根因

代码无法获取单条推文的全部图片,核心是Twitter API v1.1的两个默认机制导致的:

  • 调用user_timeline接口时没有传tweet_mode='extended'参数,接口默认返回兼容旧版的截断数据,entities.media数组只会返回单条推文中的第一张媒体资源
  • 视频、动图以及多图的完整列表不会放在基础entities字段下,需要读取extended_entities字段才能拿到全量媒体数据,转推内容的媒体还需要从retweeted_status字段里取,否则会漏采。
修复方案

按以下逻辑调整代码即可拿到全量图片、视频资源:

  • 接口请求加上tweet_mode='extended'参数,这是核心必填配置,用于获取未截断的完整推文数据
  • 优先读取extended_entities中的媒体列表,没有该字段时再回退读取entities中的媒体,兼容旧数据;遇到转推内容时,读取原推的实体字段
  • 区分媒体类型:图片直接取HTTPS协议的直链,视频/动图取最高码率的MP4地址
  • 增加一年时间窗口过滤,因为推文是按发布时间倒序返回,遇到早于一年前的内容直接终止循环即可,减少无效请求
  • 补充之前定义但未实现的点赞、转发数采集、媒体去重、结果导出逻辑
修正后完整代码
import tweepy
import pandas as pd
from datetime import datetime, timedelta

# 密钥配置
consumer_key = ''
consumer_secret = ''
access_token =''
access_token_secret = ''

auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
# 加上wait_on_rate_limit,触发限流时自动等待,无需手动处理休眠
api = tweepy.API(auth, wait_on_rate_limit=True)

media_files = set()
data = []
columns = ["image", "time", "likes", "retweets"]
# 计算一年前的UTC时间,用于时间范围过滤
one_year_ago = datetime.utcnow() - timedelta(days=365)

for status in tweepy.Cursor(
    api.user_timeline,
    screen_name='infokpgovt',
    tweet_mode='extended',
    count=200  # 单次请求拉满200条,减少请求次数
).items():
    # 超过一年时间范围直接终止循环
    if status.created_at < one_year_ago:
        break
    # 转推内容取原推的实体,否则无法获取转推里的媒体
    target_status = status
    if hasattr(status, 'retweeted_status'):
        target_status = status.retweeted_status
    # 优先取extended_entities的全量媒体列表
    media_list = []
    if hasattr(target_status, 'extended_entities') and 'media' in target_status.extended_entities:
        media_list = target_status.extended_entities['media']
    elif 'media' in target_status.entities:
        media_list = target_status.entities['media']
    
    for media in media_list:
        media_type = media['type']
        media_url = None
        # 处理图片资源
        if media_type == 'photo':
            media_url = media['media_url_https']
        # 处理视频、动图资源
        elif media_type in ['video', 'animated_gif']:
            variants = [v for v in media['video_info']['variants'] if v['content_type'] == 'video/mp4']
            if variants:
                # 按码率降序排序,取最高清的视频地址
                variants.sort(key=lambda x: x.get('bitrate', 0), reverse=True)
                media_url = variants[0]['url']
        if not media_url or media_url in media_files:
            continue
        media_files.add(media_url)
        data.append({
            "image": media_url,
            "time": status.created_at,
            "likes": status.favorite_count,
            "retweets": status.retweet_count
        })
        print(f"获取媒体地址: {media_url} | 发布时间: {status.created_at}")

# 采集结果导出为CSV文件
pd.DataFrame(data, columns=columns).to_csv('twitter_media_result.csv', index=False, encoding='utf-8-sig')
注意事项
  • 免费版Twitter API v1.1的user_timeline接口最多只能拉取账号最近3200条推文,如果目标账号一年内发推量超过这个数值,需要更换接口或升级API权限
  • 爬取到的视频直链有访问有效期,拿到地址后建议及时下载,避免链接失效
  • 初始化API时加上wait_on_rate_limit=True参数,触发平台限流时会自动等待恢复,不需要手动写休眠逻辑

内容的提问来源于stack exchange,提问作者Fakhr Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 11:54:14