instagram-private-api 数据洞察分页解析:StoriesInsightsFeedResponsePage_info 接口的 end_cursor 与 has_next_page
后端【免费下载链接】instagram-private-apiNodeJS Instagram private API SDK. Written in TypeScript.项目地址https://gitcode.com/gh_mirrors/in/instagram-private-api点击查看免费下载本篇技术指南聚焦instagram-private-apiNodeJS Instagram private API SDKTypeScript 编写中 Stories 数据洞察Story Insights分页机制的核心数据结构StoriesInsightsFeedResponsePage_info。文章将讲解该接口的定义、两个字段在游标分页中的语义并结合StoriesInsightsFeed、FeedFactory、AdsRepository等源码揭示其底层消费链路帮助读者理解并正确使用 Stories 洞察数据的翻页、可续读判断与指标提取。一、接口定义两个字段构成的分页游标契约StoriesInsightsFeedResponsePage_info定义于 src/responses/stories-insights.feed.response.ts完整声明如下export interface StoriesInsightsFeedResponsePage_info { end_cursor: string; has_next_page: boolean; }该接口仅包含两个属性却承载了 Stories 洞察数据分页的全部状态信息属性类型语义end_cursorstring当前页末尾的游标值。请求下一页时需原样回传给 GraphQL 变量的cursor字段若首页尚未携带游标则传nullhas_next_pageboolean是否存在后续页。为false表示已翻至最后一页无需继续请求在 Typedoc 文档中该接口的完整成员说明见 docs/interfaces/responses/StoriesInsightsFeedResponsePage_info.md对应的类型定义文件是 stories-insights.feed.response.ts。二、page_info 在完整响应树中的位置StoriesInsightsFeedResponsePage_info不是孤立存在的它是 Instagram Insights 图查询返回数据中Stories 网格这一层级的页信息。从 src/responses/stories-insights.feed.response.ts 的接口嵌套可以看出完整响应树StoriesInsightsFeedResponseRootObject └── data: StoriesInsightsFeedResponseData └── user: StoriesInsightsFeedResponseUser └── business_manager: StoriesInsightsFeedResponseBusiness_manager └── stories_unit: StoriesInsightsFeedResponseStories_unit └── stories: StoriesInsightsFeedResponseStories ├── edges: StoriesInsightsFeedResponseEdgesItem[] └── page_info: StoriesInsightsFeedResponsePage_info // ← 本文主题其中StoriesInsightsFeedResponseStories定义于 src/responses/stories-insights.feed.response.ts文档见 docs/interfaces/responses/StoriesInsightsFeedResponseStories.md同时持有edges每条 Story 的洞察节点与page_info分页状态。也就是说page_info与edges属于同一层级翻页时二者必须配合使用edges提供当前页数据page_info决定是否还有下一页以及下一页从哪个游标开始。每个edges元素为StoriesInsightsFeedResponseEdgesItem结构为node 恒为null的cursor其node为StoriesInsightsFeedResponseNode包含impression_count曝光数、reach_count触达数、exits_count退出数、replies_count回复数、taps_back_count/taps_forward_count回退/前进点击数、story_swipe_away_count滑走数等指标详见 docs/interfaces/responses/StoriesInsightsFeedResponseNode.md。三、page_info 的消费方StoriesInsightsFeed 的游标状态机page_info真正被使用的场景是StoriesInsightsFeed类。在 src/feeds/stories-insights.feed.ts 中statesetter 从每次响应里解构出这两个字段并同步更新内部游标与是否有更多标记protected set state(response: StoriesInsightsFeedResponseRootObject) { const { end_cursor, has_next_page } response.data.user.business_manager.stories_unit.stories.page_info; this.nextCursor end_cursor; this.moreAvailable has_next_page; }这段代码揭示了两个关键行为end_cursor→nextCursor游标被保存在Expose()装饰的私有字段nextCursor中初始为null并在下一次request()时作为 GraphQL 变量cursor回传见 src/feeds/stories-insights.feed.ts 中variables.cursor: this.nextCursorhas_next_page→moreAvailable该标记被写入基类Feed的moreAvailable字段供基类的isMoreAvailable()判断循环是否继续。request()的完整请求构造如下节选async request(): PromiseStoriesInsightsFeedResponseRootObject { const body await this.client.ads.graphQLStoriesInsightsFeedResponseRootObject({ surface: { friendlyName: IgInsightsStoryGridSurfaceQuery }, documentId: 1995528257207653, variables: { count: 15, cursor: this.nextCursor, IgInsightsGridMediaImage_SIZE: 256, queryParams: { access_token: , id: this.client.state.cookieUserId, }, timeframe: this.timeframe, }, }); this.state body; return body; }可见每次翻页请求都以固定count: 15拉取一页timeframe限定统计时间窗ONE_DAY | ONE_WEEK | TWO_WEEKS见 src/feeds/stories-insights.feed.ts。四、底层请求链路AdsRepository.graphQL 如何发出翻页请求无论是StoriesInsightsFeed的网格查询还是InsightsService.story()的单条 Story 查询最终都汇聚到广告/洞察专用的 GraphQL 通道。AdsRepository.graphQLsrc/repositories/ads.repository.ts将其封装为对/api/v1/ads/graphql/的 POST 请求public async graphQLT extends { data: any }(options: GraphQLRequestOptions): PromiseT { const { body } await this.client.request.sendT( { url: /api/v1/ads/graphql/, method: POST, qs: { locale: this.client.state.language, vc_policy: insights_policy, ...(options.surface.name ? { surface: options.surface.name } : {}), }, form: { access_token: options.accessToken, fb_api_caller_class: RelayModern, fb_api_req_friendly_name: options.surface.friendlyName, doc_id: options.documentId, variables: JSON.stringify(options.variables), }, }, true, ); return body; }与page_info直接相关的要点是variables: JSON.stringify(options.variables)——end_cursor作为variables.cursor被序列化进请求体响应中的data.user.business_manager.stories_unit.stories.page_info则作为返回类型T的一部分被解析回StoriesInsightsFeed。请求选项类型GraphQLRequestOptions定义于 src/types/graphql-request.options.ts其中friendlyName支持IgInsightsAccountInsightsSurfaceQuery、IgInsightsPostGridSurfaceQuery、IgInsightsStoryInsightsAppQuery等枚举值。五、分页主循环基类 Feed 如何利用 has_next_page 持续翻页page_info.has_next_page最终驱动基类Feedsrc/core/feed.ts的分页主循环。StoriesInsightsFeed继承自FeedRootObject, EdgesItem可直接使用其observable()方法public observable(semaphore?: () Promiseany, attemptOptions?: PartialAttemptOptionsany) { return new ObservableItem[](observer { // ... do { await retry( async () { const items await this.items(); observer.next(items); // ... }, { handleError(error, context) { // 429/500/502 等状态码时静默等待重试 }, ...(attemptOptions || this.attemptOptions), }, ); } while (this.isMoreAvailable() subscribed); observer.complete(); }); }执行流程为调用items()发请求并产出edges数据 → 通过statesetter 将page_info写入moreAvailable→while (this.isMoreAvailable())判断是否继续拉取。isMoreAvailable()的实现src/core/feed.ts为return !!this.moreAvailable即完全由has_next_page布尔值驱动。此外基类还提供items$访问器等价于this.observable()可直接订阅流式获取所有页的项内置重试策略attemptOptionssrc/core/feed.tsmaxAttempts: 10、初始延迟minDelay: 60000、重试因子factor: 1.5、jitter: true对 Instagram 的限流/临时错误做退避serialize()/deserialize()/toPlain()基于class-transformer的状态持久化可将当前游标进度序列化保存后续从nextCursor继续翻页。六、从工厂方法到翻页调用完整使用路径StoriesInsightsFeed不直接手动new其构造函数继承自Feed接收IgApiClient见 docs/classes/feeds/StoriesInsightsFeed.md而是通过FeedFactory的统一入口创建。feed.factory.ts中的工厂方法src/core/feed.factory.tspublic storiesInsights(timeframe: ONE_DAY | ONE_WEEK | TWO_WEEKS) { return plainToClassFromExist(new StoriesInsightsFeed(this.client), { timeframe }); }典型使用示例import { IgApiClient } from instagram-private-api; const ig new IgApiClient(); ig.state.generateDevice(your-username); // ... 登录与 checkpoint 处理 const storiesInsightsFeed ig.feed.storiesInsights(ONE_WEEK); for await (const edge of storiesInsightsFeed.items$) { const story edge.node; console.log({ id: story.id, instagramMediaId: story.instagram_media_id, impressionCount: story.impression_count, reachCount: story.reach_count, repliesCount: story.replies_count, }); }若仅需查询单条 Story 的洞察可改用InsightsService.story(storyId)src/services/insights.service.ts其返回类型同样是StoriesInsightsFeedResponseRootObject内部的page_info结构完全一致。InsightsService还提供account()、post()、igtv()方法文档见 docs/classes/services/InsightsService.md。七、与 PostsInsightsFeed 的对照同一套 page_info 模式page_info的分页模式并非 Stories 洞察独有。PostsInsightsFeed帖子洞察网格在 src/feeds/posts-insights.feed.ts 中实现了完全相同的游标消费逻辑protected set state(response: PostsInsightsFeedResponseRootObject) { const { end_cursor, has_next_page } response.data.user.business_manager.top_posts_unit.top_posts.page_info; this.nextCursor end_cursor; this.moreAvailable has_next_page; }两者的page_info字段类型一致end_cursor: string、has_next_page: boolean区别仅在于响应树路径stories_unit.stories与top_posts_unit.top_posts。这印证了StoriesInsightsFeedResponsePage_info所代表的是 Insights 网格查询的通用分页契约读取end_cursor回填下一次请求读取has_next_page判断是否结束。八、最佳实践与注意事项判断是否继续翻页不要依据edges数组是否为空判断应以page_info.has_next_page为准基类observable()已自动完成该判断手动调用request()时则需自行检查。游标语义首页请求传cursor: null后续页必须原样回传服务端给出的end_cursor任何改写都可能导致游标失效或跳过数据。适用前提Insights 数据属于商业账号Business Profile能力请求经由/api/v1/ads/graphql/vc_policy: insights_policy见 src/repositories/ads.repository.ts非商业账号可能返回空数据或报错timeframe仅支持ONE_DAY | ONE_WEEK | TWO_WEEKS三档。频率控制分页循环默认每页count: 15若需全量拉取需多次请求请复用基类内置的退避重试默认最大 10 次尝试、60s 起步指数退避见 src/core/feed.ts避免触发限流。类型安全请求返回类型StoriesInsightsFeedResponseRootObject与Items()返回的StoriesInsightsFeedResponseEdgesItem[]由泛型约束可直接获得完整的字段类型提示无需手写任何类型断言。赞分享后端【免费下载链接】instagram-private-apiNodeJS Instagram private API SDK. Written in TypeScript.项目地址https://gitcode.com/gh_mirrors/in/instagram-private-api点击查看免费下载相关推荐NestJS Provider Scopes 实战指南以 Comp AI CRM 为例掌握 DI 作用域与请求上下文NestJS Provider Scopes 实战指南以 Comp AI CRM 为例掌握 DI 作用域与请求上下文 导读 NestJS 依赖注入DI体系后端NanaZip右键菜单使用教程Windows 10/11资源管理器快速压缩提取完整攻略NanaZip右键菜单使用教程Windows 10/11资源管理器快速压缩提取完整攻略 NanaZip 是一款面向现代 Windows 体验的开源文件压缩工具后端instagram-private-api 数据洞察StoriesInsightsFeedResponseNode 接口全解析与 Stories 数据分析实战instagram private api 数据洞察StoriesInsightsFeedResponseNode 接口全解析与 Stories 数据分析实战后端上一篇Slidev Markdown 演示文稿工具:一个文件写好代码幻灯片,一条命令导出 PDF下一篇深入理解 continuityDocker CLI 内置的传输无关文件系统元数据清单系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考