☰
instagram-private-api 标签 Story Tray 位置贴纸响应解析:TagFeedResponseStoryLocationsItem 接口完整指南
2026/10/16 1:19:54 网站建设 项目流程
  • 后端

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

NodeJS Instagram private API SDK. Written in TypeScript.

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

导读

TagFeedResponseStoryLocationsItem是 instagram-private-api(NodeJS Instagram 私有 API SDK)中用于描述标签话题页(hashtag)Story Tray 内"位置贴纸(location sticker)"的响应数据模型。在 TypeScript 中它被定义为TagFeedResponse的嵌套接口,承载每个位置贴纸在故事画布上的坐标、尺寸、旋转角与层级信息,并内嵌一个TagFeedResponseLocation地点对象。读完本文,你将掌握该接口全部字段的含义与数据类型、它在TagFeed标签故事流中的实际 JSON 形态,以及如何通过StickerBuilder在发布端构造与之对称的位置贴纸数据,实现"读取标签页故事 → 解析地点贴纸 → 结构化使用地点信息"的完整链路。

一、接口定位:标签页 Story Tray 的贴纸清单

TagFeedResponseStoryLocationsItem不是孤立的数据类型,它隶属于标签话题 Feed 的整体响应结构。在 tag.feed.response.ts 中,TagFeedResponse顶层接口定义了标签页响应的骨架:

export interface TagFeedResponse { ranked_items: TagFeedResponseRankedItemsItem[]; items: TagFeedResponseItemsItem[]; num_results: number; next_max_id: string; more_available: boolean; auto_load_more_enabled: boolean; story: TagFeedResponseStory; status: string; }

其中story: TagFeedResponseStory是标签页顶部的 Story Tray(若干账号的最新快拍合集),其items: TagFeedResponseItemsItem[]中的每一个快拍条目(TagFeedResponseItemsItem)都可能携带一组贴纸数据,其中就包括位置贴纸:

export interface TagFeedResponseItemsItem { // ... 媒体基础字段(pk、media_type、image_versions2 等) is_reel_media?: boolean; expiring_at?: number; story_hashtags?: TagFeedResponseStoryHashtagsItem[]; creative_config?: TagFeedResponseCreative_config; reel_mentions?: TagFeedResponseReelMentionsItem[]; story_locations?: TagFeedResponseStoryLocationsItem[]; // ← 本文主角 // ... }

也就是说,一个快拍条目下通常会有"话题贴纸数组(story_hashtags)、@提及贴纸数组(reel_mentions)、位置贴纸数组(story_locations)"三类贴纸清单,TagFeedResponseStoryLocationsItem就是其中位置贴纸清单的单个元素类型,最终由 tag.feed.response.ts#L274-L284 定义。

数据来源链路

该响应来自TagFeed对 Instagram 私有接口/api/v1/feed/tag/{tag}/的请求。在 tag.feed.ts 中可以看到请求参数包含rank_token(由基类Feed用Chance生成的 GUID,见 core/feed.ts)和分页游标max_id:

async request() { const { body } = await this.client.request.send<TagFeedResponse>({ url: `/api/v1/feed/tag/${encodeURI(this.tag)}/`, qs: { rank_token: this.rankToken, max_id: this.nextMaxId, }, }); this.state = body; return body; }

TagFeed.state会把more_available与next_max_id写入内部状态,用于items$可观测流的持续翻页拉取(参见 core/feed.ts 的 retry/分页逻辑),因此标签页的快拍及其贴纸可以通过分页接口全部枚举出来。

二、接口全景:字段速览

对照 TagFeedResponseStoryLocationsItem.md 文档,该接口共 9 个属性,逐一对应源码 tag.feed.response.ts#L274-L284:

属性类型语义
xnumber \| string贴纸中心点水平坐标(归一化)
ynumber \| string贴纸中心点垂直坐标(归一化)
znumber图层层级(z 序)
widthnumber \| string贴纸宽度(占画布比例)
heightnumber \| string贴纸高度(占画布比例)
rotationnumber旋转角度(度)
is_pinnednumber是否被固定(1/0 布尔量的数值形式)
is_hiddennumber是否被隐藏(1/0 布尔量的数值形式)
locationTagFeedResponseLocation内嵌的地点对象(名称、地址、经纬度、POI ID 等)

三、字段详解:从坐标到地点对象

3.1 几何定位字段:x、y、z

  • x: number | string— 贴纸在画布上的水平位置。在 instagram-private-api 的贴纸体系中,坐标采用归一化坐标系:x、y的取值范围为 0~1,0.5代表画布正中央。这一点可以从发布端基类InstaSticker的默认值与定位方法得到印证(见 insta-sticker.ts):
    public x: number = 0.0; public y: number = 0.0; public center(): this { this.x = 0.5; this.y = 0.5; return this; }

    响应字段同时声明为number | string,从类型设计上可以推断:Instagram 服务端在不同场景下可能返回数字或字符串形式的坐标,SDK 因此用联合类型保持对两种序列化形态的兼容。

  • z: number— 图层 z 序。数字越大越靠前显示。发布端InstaSticker.moveForward(layers)/moveBackwards(layers)正是通过增减z值来调整贴纸前后遮挡关系(insta-sticker.ts)。

3.2 尺寸与旋转:width、height、rotation

  • width/height: number | string— 贴纸占故事画布的宽高比例(归一化),同样存在number | string联合类型。发布端默认值可参考:LocationSticker的默认宽高为width = 0.47、height = 0.111(见 location.sticker.ts),即位置贴纸默认横向占据画布的约 47% 宽、11% 高。
  • rotation: number— 贴纸旋转角度,单位是度(degree)。发布端rotateDeg(deg)方法会执行deg % 360.0归一化(insta-sticker.ts),因此响应中的取值通常落在 0~360 区间。

3.3 显示状态:is_pinned、is_hidden

  • is_pinned: number— 贴纸是否被"钉住"。在类型定义中它是number而非boolean,实际取值遵循 Instagram 序列化约定:1表示是,0表示否。
  • is_hidden: number— 贴纸是否处于隐藏状态(例如用户在发布后手动隐藏了该贴纸),同样是1/0数值。

3.4 核心业务字段:location: TagFeedResponseLocation

location是整个贴纸条目的"灵魂"——它承载了该贴纸对应的真实地点信息。其定义位于 tag.feed.response.ts#L84-L94:

export interface TagFeedResponseLocation { pk: number | string; // 地点的唯一主键(IG location id) name: string; // 地点显示名称 address: string; // 详细地址 city: string; // 城市 short_name: string; // 短名称(如品牌名、街区简称) lng: number | string; // 经度 lat: number | string; // 纬度 external_source: string; // 外部数据源标识(如 facebook_places) facebook_places_id: string | number; // Facebook Places 的地点 ID }

各字段用途:

  • pk可用来在后续请求中定位该地点(例如结合locationSearch反查地点详情);
  • name/address/city/short_name是可直接展示给终端用户的地点文本信息;
  • lat/lng提供了贴纸地点的精确经纬度,可用于地图渲染、距离计算或 POI 聚合;
  • external_source与facebook_places_id说明了该 POI 的底层数据来源(通常是 Facebook Places 数据库),这在做地点去重、关联商业 POI 时非常关键。

四、发布与读取的对称关系:StickerBuilder 如何生成同构数据

TagFeedResponseStoryLocationsItem描述的是"读取侧"(服务端响应)的位置贴纸形态;而在"发布侧",instagram-private-api 用StickerBuilder.location()构造完全同构的数据,二者在字段语义上一一对应。

4.1 发布侧:LocationSticker与StoryLocation

发布位置贴纸需要两层对象:

  1. 贴纸几何对象StoryLocation,继承StorySticker基类(media.configure-story.options.ts#L71-L77),拥有x、y、width、height、rotation等几何字段,并附加is_sticker: boolean与location_id: string:

    export interface StorySticker { x: number; y: number; width: number; height: number; rotation: number; } export interface StoryLocation extends StorySticker { is_sticker: boolean; location_id: string; }

    可以看到,发布侧的location_id正是读取侧TagFeedResponseLocation.pk的输入来源——贴纸的地点身份在两端是同一 ID。

  2. 贴纸构造器LocationSticker(location.sticker.ts),它确定了贴纸的唯一标识与序列化键名:

    export class LocationSticker extends InstaSticker { public locationId: string; width = 0.47; height = 0.111; get id(): string { return 'location_sticker_vibrant'; } get key(): string { return 'story_locations'; // ← 与响应字段 story_locations 同名 } }

StickerBuilder.location()(sticker-builder.ts#L82-L84)负责把普通配置对象转换成LocationSticker实例,而StickerBuilder.build()(sticker-builder.ts#L30-L52)会把贴纸按key分组、JSON 序列化,并聚合出story_sticker_ids——这正是configureToStory需要的story_locations表单载荷。

4.2 配置项约束:geotag_enabled与坐标联动

在 media.configure-story.options.ts 中有两条明确的注释约束:

// if this is set, the geotag has to be set! story_locations?: [StoryLocation] | string; geotag_enabled?: '1' | '0'; posting_latitude?: string; posting_longitude?: string; media_latitude?: string; media_longitude?: string;

设置story_locations时,必须同时开启geotag_enabled = '1'并携带经纬度四项参数,否则服务端会拒绝配置。这一点在发布服务中有完整的实现印证——publish.service.ts#L337-L347:

if (typeof options.location !== 'undefined') { const { latitude, longitude } = options.location; configureOptions.geotag_enabled = '1'; configureOptions.posting_latitude = latitude; configureOptions.posting_longitude = longitude; configureOptions.media_latitude = latitude; configureOptions.media_longitude = longitude; configureOptions.story_locations = [options.location.sticker]; configureOptions.mas_opt_in = 'NOT_PROMPTED'; }

其中options.location的类型为PostingStoryLocationSticker(posting.options.ts#L52-L55),由latitude、longitude与sticker: StoryLocation三部分组成。

4.3 序列化:stringifyStoryStickers

在最终提交configureToStory前,media.repository.ts#L401-L419 的stringifyStoryStickers会对非字符串数组的贴纸数据做JSON.stringify:

const serialize = (obj: any | undefined) => { if (typeof obj !== 'undefined' && Array.isArray(obj) && obj.length > 0 && typeof obj[0] !== 'string') { return JSON.stringify(obj); } return obj; }; form.story_hashtags = serialize(form.story_hashtags); form.story_locations = serialize(form.story_locations); // ... 其余贴纸字段同理

这说明服务端收到的story_locations是 JSON 字符串,而TagFeedResponse返回的story_locations则是反序列化后的对象数组——两端通过同一字段名story_locations完成了数据的闭环。

五、实战:读取标签页故事中的位置贴纸

综合以上链路,读取一个标签页 Story Tray 中所有位置贴纸的完整示例:

import { IgApiClient } from '../src'; import { TagFeed } from '../src/feeds'; const ig = new IgApiClient(); ig.state.generateDevice(process.env.IG_USERNAME); await ig.account.login(process.env.IG_USERNAME, process.env.IG_PASSWORD); const tagFeed: TagFeed = ig.feed.tag('foodie'); // 话题标签 const story = await tagFeed.request(); // TagFeedResponse // story.items 是该标签页 Story Tray 的快拍列表 for (const item of story.items) { // 位置贴纸是可选项:item.story_locations?: TagFeedResponseStoryLocationsItem[] if (!item.story_locations || item.story_locations.length === 0) { continue; } for (const sticker of item.story_locations) { const { location } = sticker; console.log({ mediaId: item.id, stickerGeometry: { x: sticker.x, y: sticker.y, z: sticker.z, width: sticker.width, height: sticker.height, rotation: sticker.rotation, pinned: sticker.is_pinned, hidden: sticker.is_hidden, }, place: { pk: location.pk, name: location.name, address: location.address, city: location.city, shortName: location.short_name, coordinates: { lat: location.lat, lng: location.lng }, externalSource: location.external_source, facebookPlacesId: location.facebook_places_id, }, }); } }

5.1 结合locationSearch反查地点

发布侧示例 upload-story.example.ts 展示了如何通过地点搜索接口获取真实地点 ID 来构造贴纸:

.add( StickerBuilder.location({ locationId: (await ig.locationSearch.index(13, 37)).venues[0].external_id, }), )

locationSearch.index(lat, lng)返回候选地点列表,取external_id作为locationId。该external_id与读取侧TagFeedResponseLocation.pk/facebook_places_id体系同源,可以在"搜索地点 → 发布位置贴纸 → 读取他人故事中的地点贴纸"之间建立一致的地点主键映射。

六、边界情况与注意事项

  1. 字段可选性:story_locations在TagFeedResponseItemsItem中定义为可选属性(story_locations?: TagFeedResponseStoryLocationsItem[],见 tag.feed.response.ts#L185)。并非每个标签快拍都带有位置贴纸,访问前务必做空值判断,或使用?.与?? []防御式取值。
  2. 数值联合类型:x、y、width、height是number | string,location.pk、lat、lng、facebook_places_id同理。做坐标运算或数值比较时,建议先Number()转换,避免字符串拼接导致结果异常。
  3. 数值型布尔量:is_pinned、is_hidden是number而非boolean,判断时用=== 1/=== 0,而不是直接当成 truthy 布尔值(0在 JS 中是 falsy,但2等意外值也可能出现)。
  4. is_reel_media前置条件:story_locations只出现在快拍类条目上(is_reel_media: true的条目),普通时间线帖子(items/ranked_items中的非快拍媒体)不会携带该字段。
  5. Direct Story 不支持贴纸:在发布侧,publish.service.ts#L302-L315 明确注释 "directThread => no stickers supported"——当threadIds/recipientUsers存在时configure_mode = '2'且贴纸配置被忽略。这与读取侧逻辑一致:只有发布到 Story Tray(configure_mode = '1')的内容才会在TagFeed响应中出现贴纸数据。
  6. 同构接口族:TagFeedResponseStoryLocationsItem并非唯一的位置贴纸模型。在 user-story.feed.response.ts、list-reel-media-viewer.feed.response.ts、reels-tray.feed.response.ts、location.repository.story.response.ts 等响应文件中也存在结构相近的StoryLocationsItem类型,但各自绑定不同的响应上下文(用户主页故事、快拍查看者列表、Reels Tray、地点故事)。如需通用处理,可依据本接口的几何 +location双段结构设计统一的解析器。

七、小结

TagFeedResponseStoryLocationsItem是 instagram-private-api 中"标签页故事流位置贴纸"的标准数据契约:

  • 读取侧:通过TagFeed请求/api/v1/feed/tag/{tag}/,在story.items[].story_locations[]中取得贴纸的归一化几何信息(x/y/z/width/height/rotation)、显示状态(is_pinned/is_hidden)与完整地点对象(TagFeedResponseLocation);
  • 发布侧:通过StickerBuilder.location({ locationId })+ig.publish.story({ location })构造同构数据,需满足geotag_enabled='1'与经纬度四参数联动的约束;
  • 闭环价值:两端的location_id与location.pk同源,使得"地点搜索 → 贴纸发布 → 标签故事采集 → 地点聚合分析"可以在同一个 SDK 内完成,适用于地点打卡统计、POI 热度分析、地图聚合展示等场景。

如需深入阅读接口文档与源码,可参考:

  • 接口文档:TagFeedResponseStoryLocationsItem.md(含各字段 Defined in 行号)
  • 内嵌地点对象:TagFeedResponseLocation.md
  • 源码定义:tag.feed.response.ts
  • 标签 Feed 请求:tag.feed.ts
  • 发布实现:publish.service.ts、media.repository.ts
  • 贴纸构造器:sticker-builder.ts、location.sticker.ts、insta-sticker.ts
  • 配置类型:media.configure-story.options.ts
  • 完整示例:upload-story.example.ts
  • 后端

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

NodeJS Instagram private API SDK. Written in TypeScript.

项目地址:https://gitcode.com/gh_mirrors/in/instagram-private-api
点击查看免费下载
上一篇:CodeIgniter 4 版本解读:4.0.4 的破坏性变更、新命令与增强项全解析
下一篇:A-Tune-UI未来路线图:openEuler生态系统中的性能优化愿景

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询