跳转至

平台选择

概述

igapi 支持两种客户端平台:AndroidClient,模拟 Instagram 移动端 App)和 WebWebClient,模拟浏览器)。两者共享大部分 API,但在登录方式、2FA 处理、专有功能和 session 格式上存在差异。

选对平台可以避免不必要的麻烦。本文档从功能对比到具体使用,帮助你快速做出决策。

import igapi

# Android 平台客户端(最常用)
client = igapi.Client()

# Web 平台客户端
web = igapi.WebClient()

功能对比表

特性 Client(Android) WebClient(Web)
用户信息查询 UserApi.info() 支持 支持
用户搜索 UserApi.search() 支持 不支持
用户名转 ID UserApi.id_from_username() 支持 支持
媒体信息查询 MediaApi 支持 支持
用户 Feed 获取 FeedApi 支持 支持
图片上传(移动端接口)UploadApi.photo() 支持 支持(photo_web()
图片发布配置 UploadApi.configure() 支持 支持(configure_web()
GraphQL 帖子查询 PostApi.user_posts() 不支持 支持
一步式图片发布 PostApi.create_photo() 不支持 支持
2FA 自动处理(TOTP) 不支持 支持
2FA 手动验证 需自行实现 verify_two_factor()
session 持久化 支持 支持
代理配置 支持 支持

API 访问器汇总:

API 类 Client 可用 WebClient 可用 说明
UserApi 用户信息查询和搜索
MediaApi 单条媒体信息查询
FeedApi 用户帖子分页/全量获取
UploadApi 是(部分方法) 图片上传(接口不同)
PostApi GraphQL 帖子查询 + 一步式发布(Web 独有)

推荐场景

选择 Client(Android)的场景

  • 账号没有开启 2FA,或 2FA 处理由外部系统管理
  • 需要搜索用户功能(UserApi.search(),Web 不支持)
  • 使用移动端图片上传接口(兼容性更好)
  • 主要做数据采集,不需要 GraphQL 查询
import asyncio
import igapi

async def main():
    client = igapi.Client()
    await client.login("your_username", "your_password")

    user_api = igapi.UserApi(client)

    # 搜索用户(Web 端不支持此功能)
    results = await user_api.search("travel photography")
    for user in results:
        print(f"@{user.username}: {user.follower_count} 粉丝")

    # 获取用户 Feed
    feed_api = igapi.FeedApi(client)
    items, cursor = await feed_api.user(results[0].pk)
    for item in items:
        print(f"{item.id} | 点赞:{item.like_count}")

asyncio.run(main())

选择 WebClient(Web)的场景

  • 账号开启了 2FA,希望 SDK 自动完成验证
  • 需要通过用户名直接查询公开帖子(无需先转换 user_id)
  • 需要一步式图片发布(上传 + 配置合并为单次调用)
  • 需要 GraphQL 查询获取更丰富的帖子数据
import asyncio
import igapi

async def main():
    web = igapi.WebClient()

    # 传入 TOTP Secret,SDK 自动完成 2FA 验证
    await web.login("your_username", "your_password", two_fa_secret="YOUR_TOTP_SECRET")

    post_api = igapi.PostApi(web)

    # 通过用户名直接查询(无需先获取 user_id)
    posts, cursor = await post_api.user_posts("natgeo", count=12)
    for post in posts:
        print(f"{post.id} | 点赞:{post.like_count}")

asyncio.run(main())

Android 客户端详情

登录

import asyncio
import igapi

async def main():
    client = igapi.Client()

    try:
        await client.login("your_username", "your_password")
    except igapi.TwoFactorRequired as e:
        # 抛出此异常时,e.two_factor_info 包含 2FA 元数据(dict 格式)
        # 当前版本的 Android 客户端 2FA 需手动构造后续请求
        # 建议改用 WebClient 处理 2FA 账号
        print("该账号开启了 2FA,推荐改用 WebClient")
        raise
    except igapi.ChallengeRequired as e:
        # e.challenge_info 包含挑战验证信息(dict 格式)
        # 需要在 Instagram App 中手动确认后再重试
        print("需要完成安全挑战,请在 Instagram App 中确认")
        raise
    except ValueError:
        print("密码错误或用户名无效")
        raise

asyncio.run(main())

图片上传(两步流程)

Android 平台图片上传分为两步:先上传原始文件,再配置发布:

import asyncio
import igapi

async def main():
    client = igapi.Client()
    await client.login("your_username", "your_password")

    upload_api = igapi.UploadApi(client)

    # 第一步:上传图片,获取 upload_id
    with open("photo.jpg", "rb") as f:
        image_data = f.read()

    result = await upload_api.photo(image_data)
    print(f"上传成功,upload_id:{result.upload_id}")

    # 第二步:配置并发布
    media = await upload_api.configure(
        result.upload_id,
        caption="通过 igapi 发布的帖子 #python",
        disable_comments=False,
        hide_like_count=False,
    )
    print(f"发布成功,帖子 ID:{media.id}")

asyncio.run(main())

Session 格式

Android 客户端 session 字符串的格式为:

用户名:密码||android_id;phone_id;uuid;device_id|sessionid=xxx;ds_user_id=xxx;csrftoken=xxx;mid=xxx||

导出和恢复:

from igapi import PlatformType

# 导出
account_str = client.export_account_string()
account = client.export_account()  # AccountInfo 对象

# AccountInfo 字段(Android 平台特有)
print(account.platform)    # PlatformType.Android
print(account.android_id)  # Android 设备 ID
print(account.phone_id)    # Phone ID
print(account.uuid)        # UUID
print(account.device_id)   # Device ID
print(account.user_id)     # 用户 ID(int)
print(account.session_id)  # Session ID

# 恢复
account = igapi.AccountInfo.parse(account_str, PlatformType.Android)
client = igapi.Client(account=account)

Web 客户端详情

登录(三种模式)

模式一:无 2FA 直接登录

import asyncio
import igapi

async def main():
    web = igapi.WebClient()
    await web.login("your_username", "your_password")

asyncio.run(main())

模式二:传入 TOTP Secret,自动完成 2FA(推荐)

import asyncio
import igapi

async def main():
    web = igapi.WebClient()
    # two_fa_secret 是 Authenticator App 中的密钥,Base32 编码
    await web.login("your_username", "your_password", two_fa_secret="JBSWY3DPEHPK3PXP")

asyncio.run(main())

模式三:捕获异常后手动输入验证码

import asyncio
import igapi

async def main():
    web = igapi.WebClient()

    try:
        await web.login("your_username", "your_password")
    except igapi.TwoFactorRequired:
        # verify_two_factor() 内部自动复用 login() 时的 username/password
        code = input("请输入 6 位验证码:")
        await web.verify_two_factor(code)

    print(await web.is_logged_in())  # True

asyncio.run(main())

图片发布(一步流程)

Web 平台通过 PostApi.create_photo() 将上传和发布合并为单次调用:

import asyncio
import igapi

async def main():
    web = igapi.WebClient()
    await web.login("your_username", "your_password")

    post_api = igapi.PostApi(web)

    with open("photo.jpg", "rb") as f:
        image_data = f.read()

    # 一步完成:上传 + 配置发布
    media = await post_api.create_photo(
        image_data,
        width=1080,
        height=1080,
        caption="Web 端一步式发布 #igapi",
        disable_comments=False,
        hide_like_count=False,
    )
    print(f"发布成功,帖子 ID:{media.id}")

asyncio.run(main())

也可以使用 UploadApi 的 Web 专用方法手动分步操作:

async def main():
    upload_api = igapi.UploadApi(web)

    # 第一步:Web 端上传(需要指定图片尺寸)
    result = await upload_api.photo_web(image_data, width=1080, height=1080)

    # 第二步:Web 端配置发布
    media = await upload_api.configure_web(result.upload_id, caption="手动分步发布")

Session 格式

Web 客户端 session 字符串的格式为:

用户名:密码||csrf;;;|sessionid=xxx;ds_user_id=xxx;csrftoken=xxx;mid=xxx||

导出和恢复:

from igapi import PlatformType

# 导出
account_str = web.export_account_string()
account = web.export_account()  # AccountInfo 对象

# AccountInfo 字段(Web 平台特有)
print(account.platform)    # PlatformType.Web
print(account.csrf_token)  # CSRF Token
print(account.mid)         # Machine ID
print(account.user_id)     # 用户 ID(int)

# 恢复(必须指定正确的平台类型)
account = igapi.AccountInfo.parse(account_str, PlatformType.Web)
web2 = igapi.WebClient(account=account)

如何切换平台

如果你已经在用 Android 客户端,想切换到 Web 客户端,需要重新登录获取 Web session。两种 session 格式不同,不能直接转换。

import asyncio
import igapi

async def main():
    USERNAME = "your_username"
    PASSWORD = "your_password"

    # 原有的 Android 客户端
    android_client = igapi.Client()
    await android_client.login(USERNAME, PASSWORD)

    # 创建 Web 客户端(独立登录,独立 session)
    web_client = igapi.WebClient()
    await web_client.login(USERNAME, PASSWORD)

    # 两个客户端可以同时运行,互不影响
    user_api = igapi.UserApi(android_client)
    post_api = igapi.PostApi(web_client)

asyncio.run(main())

同一程序中两种客户端可以并存,分别承担各自擅长的任务:

import asyncio
import igapi

async def main():
    # Android 客户端负责用户搜索
    android_client = igapi.Client()
    await android_client.login("your_username", "your_password")

    # Web 客户端负责帖子查询和发布
    web_client = igapi.WebClient()
    await web_client.login("your_username", "your_password")

    user_api = igapi.UserApi(android_client)
    post_api = igapi.PostApi(web_client)

    # 用 Android 搜索用户
    results = await user_api.search("travel")
    if results:
        target = results[0]
        # 用 Web 查询该用户的帖子
        posts, _ = await post_api.user_posts(target.username, count=12)
        print(f"@{target.username} 最新 {len(posts)} 条帖子")
        for post in posts:
            print(f"  {post.id} | 点赞:{post.like_count}")

asyncio.run(main())

常见问题

Q:我的账号有 2FA,只能用 WebClient 吗?

不是必须的。Android 客户端登录时如果触发 TwoFactorRequired 异常,可以从 e.two_factor_info 取出 2FA 元数据,自行构造验证请求。但这需要额外实现,工作量较大。

对于大多数场景,推荐直接使用 WebClient:传入 two_fa_secret 即可自动完成 TOTP 验证,无需任何额外代码。

Q:Android session 和 Web session 能否互相转换?

不能。两种 session 格式不同(Android 包含设备信息,Web 包含 CSRF Token),且 Instagram 服务器对两种客户端的认证方式不同,session 无法互换。切换平台需要重新登录。

Q:WebClient 的 UserApi.search() 为什么不能用?

Web 端的搜索接口与移动端不同,当前版本的 UserApi.search() 仅对接了移动端 API,因此只有 Client(Android 平台)支持。如果你同时需要搜索用户和 GraphQL 查询,可以创建两个客户端并存。

Q:PostApi.create_photo() 和 UploadApi 两步上传有什么区别?

PostApi.create_photo() 是 Web 端的一步式封装,内部将上传和发布配置合并为一次 Python 调用,使用更方便。UploadApi 的两步流程(photo_web() + configure_web())则提供更细粒度的控制,例如可以在上传后检查 upload_id 再决定是否发布。两者最终结果相同。

Q:两种客户端的 export_account_string() 格式有文档吗?

格式定义在各平台的 session 类型中:

  • Android:用户名:密码||android_id;phone_id;uuid;device_id|cookies||
  • Web:用户名:密码||csrf;;;|cookies||

其中 cookies 部分包含 sessionidds_user_idcsrftokenmid 等字段,以分号分隔。通常不需要手动拼接这个字符串,使用 export_account_string() 导出、AccountInfo.parse() 恢复即可。


相关链接