跳转至

Android 登录

概述

igapi.Client 是面向 Instagram Android 私有 API 的客户端类,也是 igapi-rs 的主要入口。 它模拟 Instagram Android 应用的请求行为,包含设备指纹、请求签名和密码加密,对外提供简洁的异步 Python 接口。

适用场景:

  • 大多数 Instagram 操作(用户信息、Feed、媒体、发帖、上传)
  • 需要稳定 session 长期运行的自动化场景
  • 对 Android 接口兼容性要求较高的场合

快速开始

import asyncio
import igapi

async def main():
    # 1. 创建客户端
    client = igapi.Client()

    # 2. 登录
    await client.login("your_username", "your_password")

    # 3. 确认登录状态
    print(await client.is_logged_in())  # True

    # 4. 导出 session,下次直接恢复,不必重新登录
    session_str = client.export_account_string()
    print(session_str)

asyncio.run(main())

Client 构造参数

参数 类型 默认值 说明
proxy str \| None None HTTP 代理地址,格式 http://host:portsocks5://host:port
danger_accept_invalid_certs bool False 跳过 TLS 证书验证。仅在使用抓包代理(如 mitmproxy、Charles)时开启,生产环境不要使用
http1_only bool False 强制使用 HTTP/1.1。配合部分抓包代理使用,避免 HTTP/2 协议问题
account AccountInfo \| None None 传入已有的 AccountInfo 对象,直接恢复已登录状态,无需重新调用 login()

使用代理示例:

client = igapi.Client(
    proxy="http://127.0.0.1:8080",
    danger_accept_invalid_certs=True,
    http1_only=True,
)

从 AccountInfo 恢复:

account = igapi.AccountInfo.parse(saved_string, platform="android")
client = igapi.Client(account=account)
# 无需再调用 login(),session 已恢复

login() 详解

方法签名

client.login(username: str, password: str) -> None

参数

参数 类型 说明
username str Instagram 用户名(不含 @
password str 账号密码,登录前会在客户端侧完成加密,不会明文传输

返回值

登录成功时返回 None,失败时抛出异常。

可能抛出的异常

异常类型 说明 建议处理方式
ValueError 密码错误(Bad password)或用户名不存在(Invalid user 检查凭证后重试
PermissionError 账号被锁定(Account locked)或需要授权确认(Consent required 在 Instagram 官方客户端解锁后重试
igapi.TwoFactorRequired 账号开启了双因素认证,需完成 2FA 参见双因素认证
igapi.ChallengeRequired 需要完成安全挑战(如邮件/手机验证) 访问 .challenge_info["checkpoint_url"] 进行验证
RuntimeError 初始化失败,通常由网络或服务端问题引起(Login init failed: ... 检查网络,稍后重试
ConnectionError HTTP 网络错误 检查网络连接或代理配置

内部行为

调用 login() 时,客户端会依次执行以下步骤:

  1. 发起预登录请求,获取服务端公钥和 key_id
  2. 使用 RSA + AES-GCM 在本地对密码进行加密
  3. 构造带有 HMAC-SHA256 签名的请求体(signed_body
  4. 发送登录请求,处理响应
  5. 将服务端返回的 sessionidds_user_id 等 cookie 写入 session 状态

完整示例

基础登录与错误处理

import asyncio
import igapi

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

    try:
        await client.login("your_username", "your_password")
        print("登录成功")

    except igapi.TwoFactorRequired as e:
        print("需要双因素认证")
        print("2FA 信息:", e.two_factor_info)
        # 参见双因素认证文档

    except igapi.ChallengeRequired as e:
        print("需要完成安全挑战")
        print("挑战链接:", e.challenge_info.get("checkpoint_url"))

    except ValueError as e:
        print(f"凭证错误: {e}")

    except PermissionError as e:
        print(f"账号受限: {e}")

    except RuntimeError as e:
        print(f"初始化失败: {e}")

    except ConnectionError as e:
        print(f"网络错误: {e}")

asyncio.run(main())

带 session 持久化的完整流程

import asyncio
import igapi
import os

SESSION_FILE = "session.txt"

async def get_client() -> igapi.Client:
    """获取已登录的客户端,优先从 session 文件恢复"""
    if os.path.exists(SESSION_FILE):
        with open(SESSION_FILE, "r") as f:
            session_str = f.read().strip()
        try:
            account = igapi.AccountInfo.parse(session_str, platform="android")
            client = igapi.Client(account=account)
            if await client.is_logged_in():
                print("从 session 文件恢复成功")
                return client
        except Exception as e:
            print(f"session 恢复失败,重新登录: {e}")

    # 全新登录
    client = igapi.Client()
    await client.login(
        os.environ["IG_USERNAME"],
        os.environ["IG_PASSWORD"],
    )

    # 保存 session
    with open(SESSION_FILE, "w") as f:
        f.write(client.export_account_string())
    print("登录成功,session 已保存")
    return client


async def main():
    client = await get_client()
    # 后续正常使用 client...

asyncio.run(main())

注意事项

  • 密码安全AccountInfo 字符串中包含明文密码,请勿将其提交到版本控制系统或共享给他人。建议通过文件权限或加密存储保护该字符串。

  • 不要频繁重新登录:每次登录都会消耗一定的风控配额,建议通过 session 持久化避免重复登录。session 过期后再重新登录即可。

  • 代理配置:同一 Client 实例的所有请求会使用同一个代理。如需切换代理,请创建新的 Client 实例。

  • 线程安全Client 实例可以在多线程环境中安全调用,内部 session 状态使用读写锁保护。但同一实例不建议同时发起大量并发请求,会触发 Instagram 的速率限制。

  • is_logged_in() 的局限性:该方法仅检查内存中的 session 状态是否存在,不会发起网络请求验证 session 是否仍然有效。如需验证,可尝试调用 client.user().info_by_name("some_user") 等 API。


常见问题

Q: 登录时报 RuntimeError: Login init failed,是什么原因?

A: 通常是网络问题或 Instagram 服务器短暂不可用。建议检查网络连接、代理配置,然后稍后重试。如果长期出现,请检查 User-Agent 和设备信息是否异常。

Q: 刚登录成功,再次运行程序时提示 session 无效怎么办?

A: Instagram session 在以下情况会失效:密码被修改、账号在其他设备强制退出、长时间未使用(通常数周至数月)。建议捕获 PermissionErrorSession expired)并重新登录。

Q: 使用 account= 恢复时,还需要调用 login() 吗?

A: 不需要。传入 AccountInfo 后,客户端会直接使用其中的 session cookies,无需再次登录。但如果 session 已过期,后续 API 调用会抛出 PermissionError,此时需要重新创建 Client() 并调用 login()

Q: 账号开启了双因素认证,登录流程如何处理?

A: Client.login() 仅支持无 2FA 的 Android 登录。如果账号开启了 2FA,login() 会抛出 igapi.TwoFactorRequired。对于需要 2FA 的账号,推荐使用 WebClient,它支持通过 two_fa_secret 参数自动完成 TOTP 验证。详见双因素认证文档。

Q: 登录后调用 API 报 PermissionError: Login required,为什么?

A: 这通常意味着 session 已过期或从未成功登录。请确认 client.is_logged_in() 返回 True,或捕获此异常后重新调用 login()