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:port 或 socks5://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() 详解¶
方法签名¶
参数¶
| 参数 | 类型 | 说明 |
|---|---|---|
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() 时,客户端会依次执行以下步骤:
- 发起预登录请求,获取服务端公钥和
key_id - 使用 RSA + AES-GCM 在本地对密码进行加密
- 构造带有 HMAC-SHA256 签名的请求体(
signed_body) - 发送登录请求,处理响应
- 将服务端返回的
sessionid、ds_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 在以下情况会失效:密码被修改、账号在其他设备强制退出、长时间未使用(通常数周至数月)。建议捕获 PermissionError(Session 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()。