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
相关产品推荐
相关产品推荐

