- 后端
【免费下载链接】instagram-private-api
NodeJS Instagram private API SDK. Written in TypeScript.
本文基于 instagram-private-api 仓库中 TypeDoc 自动生成的接口文档 ReelsMediaFeedResponseTalliesItem,围绕ReelsMediaFeedResponseTalliesItem这一响应模型展开:它是 Reels 媒体信息流(/api/v1/feed/reels_media/)中投票贴纸(poll)与问答贴纸(quiz)选项计票结果的最小数据单元。读完后你将掌握该接口三个字段(text、font_size、count)的语义与来源、它在响应树中的挂载位置(poll_sticker.tallies/quiz_sticker.tallies),以及如何通过ReelsMediaFeed发起请求拿到包含这些字段的数据,并与 SDK 写入侧的PollSticker、QuizSticker构建器对照理解同名字段的往返关系。
一、接口定义与三个字段
ReelsMediaFeedResponseTalliesItem定义在 src/responses/reels-media.feed.response.ts#L105-L109 中,是描述“某个互动选项当前计票情况”的 TypeScript 接口:
export interface ReelsMediaFeedResponseTalliesItem { text: string; // 选项文本,例如 "Yes" / "No",或 quiz 的备选项文案 font_size?: number; // 可选:贴纸内该选项文本的字体大小 count: number; // 当前该选项的投票/作答数量 }对应文档页中的字段说明如下(与原文档一一对应):
| 字段 | 类型 | 必填 | 源码位置 | 说明 |
|---|---|---|---|---|
text | string | 是 | reels-media.feed.response.ts:106 | 选项文本内容 |
font_size | number | 否(Optional) | reels-media.feed.response.ts:107 | 选项文本的字体大小,服务端不一定返回 |
count | number | 是 | reels-media.feed.response.ts:108 | 该选项的累计计数 |
该接口文件通过 src/responses/index.ts#L54 的export * from './reels-media.feed.response'统一导出,因此可以在项目任意处以ReelsMediaFeedResponseTalliesItem名称直接导入使用。
一份符合该结构的 JSON 示例(投票贴纸两个选项各 3 票 / 1 票):
{ "text": "Yes", "font_size": 28.0, "count": 3 }二、它在 Reels 响应树中的挂载位置
从源码结构看,ReelsMediaFeedResponseTalliesItem并不是顶层字段,而是嵌套在互动贴纸对象内部的tallies数组元素类型,共有两处引用,都在同一个响应文件中:
- 投票贴纸
ReelsMediaFeedResponsePollSticker(src/responses/reels-media.feed.response.ts#L94-L104):
export interface ReelsMediaFeedResponsePollSticker { id: string; poll_id: number; question: string; tallies: ReelsMediaFeedResponseTalliesItem[]; promotion_tallies: null; viewer_can_vote: boolean; viewer_vote?: number; is_shared_result: boolean; finished: boolean; }- 问答贴纸
ReelsMediaFeedResponseQuizSticker(src/responses/reels-media.feed.response.ts#L144-L156):
export interface ReelsMediaFeedResponseQuizSticker { id: string; quiz_id: number; question: string; tallies: ReelsMediaFeedResponseTalliesItem[]; correct_answer: number; // 正确答案在 tallies 中的下标 viewer_can_answer: boolean; finished: boolean; text_color: string; start_background_color: string; end_background_color: string; viewer_answer?: number; // 当前查看者所选答案下标 }贴纸外层还有一层“贴纸画布”容器ReelsMediaFeedResponseStoryPollsItem/ReelsMediaFeedResponseStoryQuizsItem(L82-L93、L132-L143),携带x/y/z、width/height、rotation、is_pinned、is_hidden、is_sticker等布局字段,分别对应单条 Reels 媒体ReelsMediaFeedResponseItem上的可选数组属性story_polls、story_quizs(L76-L79)。也就是说,只有当一条 Reels 确实携带投票或问答贴纸时,你才能在story_polls[].poll_sticker.tallies/story_quizs[].quiz_sticker.tallies路径上读到ReelsMediaFeedResponseTalliesItem[]数组。
几个消费侧的实用判断点:
- 通过
count求和与比较,可以还原投票/答对的实时比例; - 对 quiz 而言,
correct_answer与viewer_answer都是“tallies 下标”而非文本匹配,配合每个TalliesItem.text才能知道选项含义; - 贴纸容器的
is_hidden/is_pinned等标记会影响贴纸在客户端上的展示形态,解析时建议保留; font_size是可选字段,做数值运算(例如按字号渲染)前需要判空。
三、数据来源:ReelsMediaFeed 的请求与扁平化逻辑
ReelsMediaFeedResponseTalliesItem所在的完整响应由ReelsMediaFeed类拉取。该类的实现见 src/feeds/reels-media.feed.ts,类文档见 docs/classes/feeds/ReelsMediaFeed.md。其request()方法向私有接口发起签名 POST 请求:
async request() { const { body } = await this.client.request.send<ReelsMediaFeedResponseRootObject>({ url: `/api/v1/feed/reels_media/`, method: 'POST', form: this.client.request.sign({ user_ids: this.userIds, source: this.source, // 默认 'feed_timeline' _uuid: this.client.state.uuid, _uid: this.client.state.cookieUserId, _csrftoken: this.client.state.cookieCsrfToken, device_id: this.client.state.deviceId, supported_capabilities_new: JSON.stringify(SUPPORTED_CAPABILITIES), }), }); return body; }请求参数要点:
user_ids:要拉取 Reels 的用户 ID 数组(Array<number | string>),来自 src/feeds/reels-media.feed.ts#L7;source:请求来源模块标识,默认'feed_timeline',类型为IgAppModule(src/types/common.types.ts#L3-L33),表示该请求模拟自 App 内哪个入口;- 其余
_uuid、_uid、_csrftoken、device_id、supported_capabilities_new由客户端登录态与设备指纹填充,其中能力清单来自 src/samples/supported-capabilities.json。
响应根对象为ReelsMediaFeedResponseRootObject,形如{ reels: { [pk]: ReelsMediaFeedResponse }, status: string }:reels是以用户pk为键的映射,每个用户对应一个包含items(Reels 媒体列表)的集合。items()方法会把各用户的items展平成一个数组返回:
async items(): Promise<ReelsMediaFeedResponseItem[]> { const body = await this.request(); return Object.values(body.reels).reduce( (accumulator, current: ReelsMediaFeedResponse) => accumulator.concat(current.items), [], ); }调用方式经由FeedFactory创建,见 src/core/feed.factory.ts#L153-L155:
public reelsMedia(options: { userIds: Array<number | string>; source?: IgAppModule }): ReelsMediaFeed { return plainToClassFromExist(new ReelsMediaFeed(this.client), options); }IgApiClient上的入口属性为feed(src/core/client.ts#L45 中public feed = new FeedFactory(this)),因此典型消费代码为:
import { IgApiClient } from 'instagram-private-api'; const ig = new IgApiClient(); // ... 配置设备指纹并 await ig.account.login(options) 后: const feed = ig.feed.reelsMedia({ userIds: [123456789] }); const items = await feed.items(); for (const item of items) { const polls = item.story_polls ?? []; for (const slot of polls) { console.log(slot.poll_sticker.question, slot.poll_sticker.tallies); // tallies: ReelsMediaFeedResponseTalliesItem[] // 例如 [{ text: 'Yes', font_size: 28.0, count: 3 }, { text: 'No', count: 1 }] } }此外,ReelsMediaFeed继承自 src/core/feed.ts 的Feed基类,除了items()还可使用items$/observable()获得 RxJS 订阅,基类内置的attemptOptions提供默认重试策略(最多 10 次尝试、带抖动的指数退避,见 src/core/feed.ts#L10-L17),适合长轮询场景。注意ReelsMediaFeed覆写了set state(body) {}为空实现且未维护moreAvailable,因此isMoreAvailable()恒为false,observable()只会发出一次数据。
四、与写入侧的对照:PollSticker 与 QuizSticker 的 tallies 构造
理解ReelsMediaFeedResponseTalliesItem的读取语义后,SDK 的写入侧(sticker-builder)提供了同构的“发”向模型,二者在text/count/font_size维度上形成对照:
- PollSticker(src/sticker-builder/stickers/poll.sticker.ts):其
tallies为固定两元素的[PollStickerTallie, PollStickerTallie],其中PollStickerTallie仅含text与可选fontSize。注意 setter 会对每一项注入默认字号:
set tallies(value: Tallies) { this._tallies = value.map(t => ({ fontSize: 28.0, ...t })) as Tallies; }这正是响应中font_size常见值为28.0的来源(显式赋值的项会覆盖默认值)。该贴纸id为polling_sticker_vibrant、序列化键为story_polls,默认宽高0.49934897/0.1266892(L28-L37)。
QuizSticker(src/sticker-builder/stickers/quiz.sticker.ts):
options接受Array<{ text: string; count: number }>,也支持纯字符串数组自动补count: 0;其id为quiz_story_sticker_default、序列化键为story_quizs,与响应侧quiz_sticker.tallies的下标语义(correct_answer/viewer_answer)一一对应。configure 参数类型
StoryPollTallie(src/types/media.configure-story.options.ts#L137-L142)对font_size给出了取值约束注释range: 17.5 .. 35.0,且要求count: 0、viewer_vote: 0、viewer_can_vote: true(新建投票时的初始状态)。这与读取侧“count由服务端累计”的语义互为印证:发出去时从零开始,读回来时才是真实票数。
五、相似结构在其他响应中的复用
从源码结构看,{ text, count, font_size? }这一“计票项”三元组在多个响应文件中被重复建模,说明它是 Instagram 贴纸体系里稳定的通用形态。除本文主角外,仓库中还有:
- ReelsTrayFeedResponseTalliesItem:Reels 托盘信息流(
reelsTray)中 poll/quiz 贴纸的计票项,字段与本文接口完全一致; - MediaUpdatedMediaResponseTalliesItem:configure 后返回的
updated_media中投票贴纸的计票项; - HighlightsRepositoryEditReelResponseTalliesItem:编辑精选集(highlight reel)响应中的同名数组。
这意味着如果你已在reelsMedia中解析过ReelsMediaFeedResponseTalliesItem,同样的解析逻辑(按text匹配选项、比较count、必要时判空font_size)可以平移到托盘流与 updated media 场景,只是外层贴纸字段的类型名不同。
六、使用注意事项小结
- 可选性:
font_size为Optional,且整条链路(story_polls/story_quizs数组本身)均为可选,解析前建议逐级判空; - 下标语义:quiz 的
correct_answer、viewer_answer与 poll 的viewer_vote都是tallies数组下标,切勿与选项文本硬编码绑定; - 状态字段:
finished/viewer_can_vote/viewer_can_answer决定了贴纸当前是否仍可互动,展示结果时应结合这些布尔位判断是否展示百分比; - 请求前提:
reelsMedia需要已登录的IgApiClient(state中具备cookieUserId、csrfToken、deviceId等),且user_ids目标用户对当前会话可见,否则响应中对应reels键可能缺失或为空; - 字段对齐:与写入侧
StoryPollTallie.font_size(17.5 ~ 35.0)及PollSticker默认28.0对照,可辅助校验异常字号值。
以上结论均以当前仓库源码为准:接口定义见 src/responses/reels-media.feed.response.ts,请求实现见 src/feeds/reels-media.feed.ts,构建器实现见 src/sticker-builder/stickers/poll.sticker.ts 与 src/sticker-builder/stickers/quiz.sticker.ts。
- 后端
【免费下载链接】instagram-private-api
NodeJS Instagram private API SDK. Written in TypeScript.
相关推荐
instagram-private-api 中 ReelsMediaFeedResponseStoryPollsItem 接口详解:解析 Reels/Story 投票贴纸的响应结构
instagram private api 中 ReelsMediaFeedResponseStoryPollsItem 接口详解:解析 Reels/Story
后端tldr 别名页面机制解析:以 `ic` → `ibmcloud` 为例
tldr 别名页面机制解析:以 ic → ibmcloud 为例 tldr 通过“别名页面(alias page)”机制,为那些只是其他命令快捷方式的命令提供引
后端instagram-private-api 中 ReelsMediaFeedResponseStoryQuestionsItem 接口详解:解析 Story(快拍)问答贴纸的响应结构
instagram private api 中 ReelsMediaFeedResponseStoryQuestionsItem 接口详解:解析 Story(快
后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考