news 2026/10/16 2:31:02

instagram-private-api 响应接口解析:UserStoryFeedResponseImage_versions2 与用户故事图片候选机制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
instagram-private-api 响应接口解析:UserStoryFeedResponseImage_versions2 与用户故事图片候选机制
  • 后端

【免费下载链接】instagram-private-api

NodeJS Instagram private API SDK. Written in TypeScript.

项目地址:https://gitcode.com/gh_mirrors/in/instagram-private-api
点击查看免费下载

本篇文章聚焦 instagram-private-api(NodeJS Instagram 私有 API SDK,TypeScript 编写)中用户故事(Stories)数据流的核心图片接口 ——UserStoryFeedResponseImage_versions2。该接口承载 Instagram 对单条 Story 图片的“多分辨率候选(candidates)”描述,是开发者在拉取用户 Story、选择最佳画质、实现缩略图加载等场景中必须理解的数据结构。读完本文,你将掌握该接口在响应树中的精确位置、每个字段的含义与取值范围,以及如何通过UserStoryFeed与FeedFactory.userStory()实际取到并使用这些图片数据。

接口概述:一条属性撑起整个图片选择逻辑

UserStoryFeedResponseImage_versions2定义在 src/responses/user-story.feed.response.ts,接口本体极其精炼:

export interface UserStoryFeedResponseImage_versions2 { candidates: UserStoryFeedResponseCandidatesItem[]; }

它只有一个属性candidates,类型为UserStoryFeedResponseCandidatesItem[]。该接口在官方 TypeDoc 文档中登记于 docs/interfaces/responses/UserStoryFeedResponseImage_versions2.md,归属于responses模块(docs/modules/responses.md)。字段解析如下:

字段类型说明
candidatesUserStoryFeedResponseCandidatesItem[]同一张 Story 图片的多个分辨率候选版本数组,按 Instagram 服务端生成的多种尺寸组织

“Image_versions2”(image_versions2)是 Instagram API 中一个约定俗成的命名:它表明服务端为同一条媒体内容提供了多份规格不同的图片版本,客户端可以根据屏幕尺寸、网络条件与缓存策略选择最合适的一版。

候选条目:UserStoryFeedResponseCandidatesItem 详解

candidates数组中的每一项由UserStoryFeedResponseCandidatesItem描述,定义于 src/responses/user-story.feed.response.ts:

export interface UserStoryFeedResponseCandidatesItem { width: number; height: number; url: string; estimated_scans_sizes?: number[]; }

对应文档见 docs/interfaces/responses/UserStoryFeedResponseCandidatesItem.md,字段语义如下:

  • width/height(number):该候选图片的像素宽高。Instagram 通常为一条 Story 返回若干个由小到大的尺寸档位,例如 1080×1920 的原始尺寸以及若干缩放后的版本。可用它们判断“原图”与“缩略图”。
  • url(string):候选图片的 CDN 直链。该链接为 Instagram 内容分发地址,可直接用于下载、展示或二次处理(如本地缓存、缩略图生成)。
  • estimated_scans_sizes(可选,number[]):可选的“估算扫描体积”数据,用于客户端在弱网环境下预估每个候选版本的下载代价;并非每个响应都会携带该字段,因此在类型上标记为可选(?)。

多版本选择的意义

从源码结构可以推断,Instagram 之所以返回多档candidates,是为了让客户端在“画质”与“流量/速度”之间做权衡:列表靠前通常更接近原始分辨率,靠后的则是降采样版本。实践中可以按Math.max(width)选取最清晰的版本,或按宽度阈值选取适合手机屏幕的版本。

在响应树中的位置:从 RootObject 到图片

UserStoryFeedResponseImage_versions2不是孤立接口,它嵌在用户故事 feed 的完整响应树中。整棵响应结构定义于同一文件 src/responses/user-story.feed.response.ts,层级如下:

UserStoryFeedResponseRootObject ├── broadcast: null ├── status: string └── reel: UserStoryFeedResponseReel ├── id / latest_reel_media / expiring_at / seen ├── can_reply / can_reshare / reel_type ├── user: UserStoryFeedResponseUser // pk、username、full_name、is_private 等 ├── items: UserStoryFeedResponseItemsItem[] // 每条 Story 的条目 └── media_count / has_besties_media / ... └── items[] 中的每个条目 UserStoryFeedResponseItemsItem ├── taken_at / pk / id / media_type / code ├── image_versions2: UserStoryFeedResponseImage_versions2 ← 本文主角 ├── original_width / original_height └── ...(video_versions、story_locations、caption 等可选字段)

UserStoryFeedResponseItemsItem(src/responses/user-story.feed.response.ts)中的image_versions2字段正是UserStoryFeedResponseImage_versions2类型,同时它还与original_width、original_height相伴出现,便于开发者对照“原始尺寸”与“候选尺寸”。

值得注意的是:该条目既可能描述图片型 Story,也可能描述视频型 Story(此时会附带video_versions、video_dash_manifest、video_duration等视频字段)。因此实际使用时,可先通过media_type判断媒体类型,再决定读取image_versions2还是视频版本数组。

实战:如何取到用户的 Story 图片

通过 FeedFactory 创建 UserStoryFeed

UserStoryFeed类实现于 src/feeds/user-story.feed.ts,其核心请求逻辑指向GET /api/v1/feed/user/{userId}/story/,并附带supported_capabilities_new查询参数(序列化自client.state.supportedCapabilities):

async request(): Promise<UserStoryFeedResponseRootObject> { const { body } = await this.client.request.send({ url: `/api/v1/feed/user/${this.userId}/story/`, method: 'GET', qs: { supported_capabilities_new: JSON.stringify(this.client.state.supportedCapabilities), }, }); return body; } async items(): Promise<UserStoryFeedResponseItemsItem[]> { const response = await this.request(); if (!response.reel) { return []; } return response.reel.items; }

创建该 Feed 的推荐入口是 src/core/feed.factory.ts 中的工厂方法:

public userStory(userId: string | number): UserStoryFeed { return plainToClassFromExist(new UserStoryFeed(this.client), { userId }); }

即通过ig.feed.userStory(userId)获取某位用户(注意这里只是“当前用户”视角下的指定用户 ID)当前可看的 Story feed。

结合登录与搜索的完整示例

仓库提供了可直接运行的最小示例 examples/user-stories-watching.example.ts,其流程覆盖了从登录到读取图片数据的完整链路:

import 'dotenv/config'; import { IgApiClient } from '../src'; (async () => { const ig = new IgApiClient(); ig.state.generateDevice(process.env.IG_USERNAME); ig.state.proxyUrl = process.env.IG_PROXY; const auth = await ig.account.login(process.env.IG_USERNAME, process.env.IG_PASSWORD); const targetUser = await ig.user.searchExact('username'); // 按用户名精确找到目标用户 const reelsFeed = ig.feed.reelsMedia({ // 或改用 reelsMedia 批量拉取多个用户 userIds: [targetUser.pk], }); const storyItems = await reelsFeed.items(); // 得到 ReelsMediaFeedResponseItem[] if (storyItems.length === 0) { console.log(`${targetUser.username}'s story is empty`); return; } const seenResult = await ig.story.seen([storyItems[0]]); // 标记已看 console.log(seenResult.status); // "ok" })();

若改用ig.feed.userStory(targetUser.pk),items()返回的便是UserStoryFeedResponseItemsItem[],随后即可这样提取图片:

for (const item of storyItems) { // 仅当为图片型 Story(media_type === 1)时取 image_versions2 const candidates = item.image_versions2.candidates; const best = candidates.reduce((a, b) => (a.width * a.height > b.width * b.height ? a : b)); console.log(`最佳分辨率: ${best.width}x${best.height} -> ${best.url}`); }

示例中提到,feed.reelsMedia与feed.userStory的items()返回结构略有差异:前者是ReelsMediaFeedResponseItem,后者是UserStoryFeedResponseItemsItem,但二者的image_versions2结构是同一套“candidates 数组”模式。

标记已看:Story 消费闭环

拿到图片与条目后,可通过 src/services/story.service.ts 的StoryService.seen()向 Instagram 上报“已看”。其实现会按mediaPk_userPk_sourceId组装 key,并随机为每条 Story 的seenAt增加 1–3 秒以模拟真人浏览节奏。最终落到底层 src/repositories/media.repository.ts 的media.seen(),请求POST /api/v2/media/seen/,携带reel: 1、live_vod: 0等参数。这构成了“拉取 Story 图片 → 展示 → 标记已看”的完整业务闭环。

与其他 Feed 中同构结构的横向对照

image_versions2 → candidates[]并非用户故事 feed 独有,它是 Instagram API 各响应中反复出现的“图片版本”惯用结构。仓库中可找到大量同构定义:

  • ReelsMediaFeedResponseImageVersions2:src/responses/reels-media.feed.response.ts(对应批量拉取多个用户 Story 的 src/feeds/reels-media.feed.ts)
  • HighlightsRepositoryHighlightsTrayResponseImage_versions2:src/responses/highlights.repository.highlights-tray.response.ts
  • LikedFeedResponseImage_versions2:src/responses/liked.feed.response.ts
  • DirectThreadRepositoryApproveParticipantRequestResponseImage_versions2:src/responses/direct-thread.repository.approve-participant-request.response.ts
  • IgtvBrowseFeedResponseImage_versions2:src/responses/igtv.browse.feed.response.ts(IGTV 版本还额外携带additional_candidates)

从源码结构看,这些接口的差异主要在“附加字段”(如 IGTV 的additional_candidates)与候选条目字段的细节上:例如ReelsMediaFeedResponseCandidatesItem只有width/height/url三字段(src/responses/reels-media.feed.response.ts),而UserStoryFeedResponseCandidatesItem多出一个可选的estimated_scans_sizes。理解这套通用模式后,无论面对哪个 feed 的响应类型,都能快速定位到图片直链。

使用注意事项

  • 登录前置:所有 feed 请求都依赖已认证的IgApiClient会话(account.login),未登录会触发IgLoginRequiredError(见 src/errors 目录)。
  • 可选字段防御:estimated_scans_sizes、story_locations、video_versions等字段在类型上均为可选(?),读取前建议判空。
  • 空 Story 处理:UserStoryFeed.items()在response.reel为空时会返回[](src/feeds/user-story.feed.ts),业务层应据此判断“该用户当前没有可看的 Story”。
  • 频率控制:Feed基类(src/core/feed.ts)内置了基于@lifeomic/attempt的重试策略,默认对 400/429/500/502 等状态码自动退避等待(初始 60s、最大 300s、最多 10 次),大规模批量拉取时应尊重该机制,避免触发 Instagram 风控。

总结

UserStoryFeedResponseImage_versions2虽然只是一个仅含candidates属性的薄封装接口,但它是整个用户故事图片数据的“最后一公里”:向上承接UserStoryFeedResponseItemsItem.image_versions2,向下连接每个候选条目的尺寸与 CDN 直链。配合FeedFactory.userStory()、StoryService.seen()以及 examples/user-stories-watching.example.ts 中的完整示例,开发者可以据此实现 Story 拉取、多分辨率图片选择、下载缓存与已看上报等完整能力。

  • 后端

【免费下载链接】instagram-private-api

NodeJS Instagram private API SDK. Written in TypeScript.

项目地址:https://gitcode.com/gh_mirrors/in/instagram-private-api
点击查看免费下载
上一篇:OpenCore Legacy Patcher:突破苹果硬件限制的3大技术突破与逆向兼容方案
下一篇:终极3DS格式转换指南:从CCI到CIA的完整解决方案

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/16 2:26:55

虚拟陀螺仪(软陀螺)适用角速度范围技术分析

摘要本文档详细分析了虚拟陀螺仪技术的特点、工作原理及其适用的角速度范围。通过对比虚拟陀螺仪与物理陀螺仪的性能差异&#xff0c;为不同应用场景的选择提供技术参考。1. 虚拟陀螺仪概述1.1 技术定义虚拟陀螺仪是一种基于软件算法的解决方案&#xff0c;通过融合加速度计和磁…

作者头像 李华
网站建设 2026/10/16 2:24:00

递归导致栈溢出的底层原理与排查修复实战

去年接手的一个服务突然在线上崩了&#xff0c;日志里全是stack overflow之类的报错&#xff0c;当时团队的第一反应是“有死循环”&#xff0c;结果查了半天发现代码逻辑没有任何死循环&#xff0c;真正的原因是某条业务数据的嵌套层级太深&#xff0c;一个普通的递归函数把函…

作者头像 李华
网站建设 2026/10/16 2:23:55

【C++修炼】模板初阶:泛型编程、函数模板、类模板

目录 模板初阶 一、泛型编程 二、函数模板 2.1 函数模板概念 2.2 函数模板格式 2.3 函数模板的原理 2.4 函数模板的实例化 2.5 模板参数的匹配原则 三、类模板 3.1 类模板的定义格式 3.2 类模板的实例化 模板初阶 一、泛型编程 代码示例 1.1 // C语言实现多种参数…

作者头像 李华