跳转至

代理配置

概述

在以下场景中,为 igapi 客户端配置代理非常必要:

调试与逆向分析:使用 Charles、mitmproxy 等抓包工具截获并分析 Instagram 的请求和响应,有助于理解 API 行为、排查异常。

网络访问限制:在某些网络环境中,直连 Instagram 服务器存在障碍,需要通过代理节点转发流量。

安全隔离:在自动化测试或批量操作场景中,通过代理对出口 IP 进行统一管理,避免同一 IP 下并发请求过多触发风控。

igapi.android.latest.Clientigapi.ios.latest.Clientigapi.web.latest.Client 均在构造时支持代理相关参数,无需修改系统全局代理即可生效。代理必须通过 igapi.Proxy 对象传入,避免把普通 HTTP CONNECT 代理误写成 HTTPS 代理端点。


基本代理配置

所有客户端构造函数接受相同的代理参数,在实例化时传入即可:

import igapi

# Android 客户端(登录后使用)
client = igapi.android.latest.Client(
    proxy=igapi.Proxy.http("127.0.0.1", 8080),
    danger_accept_invalid_certs=True,
    http1_only=True,
)

# Web 客户端
web = igapi.web.latest.Client(
    proxy=igapi.Proxy.http("127.0.0.1", 8080),
    danger_accept_invalid_certs=True,
    http1_only=True,
)

不使用代理时,三个参数均可省略,客户端直接连接 Instagram 服务器:

# 不使用代理(默认行为)
client = igapi.android.latest.Client()
web = igapi.web.latest.Client()

配合 Charles / mitmproxy 抓包

Charles 配置步骤

  1. 启动 Charles,默认监听 127.0.0.1:8888
  2. 在 Charles 中开启 SSL Proxying(Proxy → SSL Proxying Settings),添加 *.instagram.com*.cdninstagram.com
  3. 在代码中配置客户端:
import asyncio
import igapi

# 配合 Charles 抓包
client = igapi.android.latest.Client(
    proxy=igapi.Proxy.http("127.0.0.1", 8888),
    danger_accept_invalid_certs=True,  # 信任 Charles 自签证书
    http1_only=True,                   # Charles 不支持 HTTP/2,强制降级
)

web = igapi.web.latest.Client(
    proxy=igapi.Proxy.http("127.0.0.1", 8888),
    danger_accept_invalid_certs=True,
    http1_only=True,
)

async def main():
    # 正常调用,所有请求均经 Charles 转发
    await web.login("用户名", "密码")

asyncio.run(main())

mitmproxy 配置步骤

  1. 启动 mitmproxy,默认监听 127.0.0.1:8080
# 启动 mitmproxy 控制台界面
mitmproxy --listen-port 8080

# 或者启动 Web 界面(浏览器访问 http://127.0.0.1:8081)
mitmweb --listen-port 8080 --web-port 8081

# 或者仅输出到终端
mitmdump --listen-port 8080
  1. 在代码中配置客户端:
import igapi

# 配合 mitmproxy 抓包
client = igapi.android.latest.Client(
    proxy=igapi.Proxy.http("127.0.0.1", 8080),
    danger_accept_invalid_certs=True,  # 信任 mitmproxy 自签证书
    http1_only=True,
)

Web SOCKS 代理

注意:SOCKS5 支持当前面向 Web 客户端的 wreq 传输层。Android/iOS 代理优先使用普通 HTTP CONNECT 代理。

如需使用 SOCKS 代理,优先使用 socks5h,让代理端解析 Instagram 域名:

import igapi

# SOCKS5H 代理(不含认证)
proxy = igapi.Proxy(
    proxy_type=igapi.ProxyType.SOCKS5H,
    host="127.0.0.1",
    port=1080,
)
client = igapi.web.latest.Client(
    proxy=proxy,
)

# SOCKS5H 代理(含用户名密码认证)
proxy = igapi.Proxy(
    proxy_type=igapi.ProxyType.SOCKS5H,
    host="代理服务器",
    port=1080,
    username="用户名",
    password="密码",
)
client = igapi.web.latest.Client(proxy=proxy)

参数说明

参数名 类型 默认值 说明
proxy Proxy \| None None 代理配置对象。Android/iOS 当前支持 Proxy.http(...) / Proxy.https(...);Web 支持 httphttpssocks4socks4asocks5socks5h。默认 None 表示不使用代理,Web 客户端不读取 HTTP_PROXY / HTTPS_PROXY / ALL_PROXY 环境变量
danger_accept_invalid_certs bool False 跳过 TLS 证书验证。抓包代理(Charles、mitmproxy)使用自签证书,必须设为 True 才能正常建立 HTTPS 连接。仅用于开发调试,生产环境禁止开启
http1_only bool False 强制使用 HTTP/1.1,禁用 HTTP/2。部分代理软件不支持 HTTP/2 协议,开启此项可提高兼容性

Proxy.from_url(...) 仍可解析 http://host:portsocks5h://host:porthost:porthost:port:user:pass,但解析结果也必须先变成 Proxy 对象再传给客户端。


完整示例:配合 mitmproxy 分析登录请求

以下示例演示如何通过 mitmproxy 完整抓取 Web 平台的登录请求,用于分析请求头和请求体结构。

第一步:在终端启动 mitmproxy

mitmweb --listen-port 8080 --web-port 8081

第二步:运行以下 Python 脚本

import asyncio
import igapi


async def analyze_login():
    """通过 mitmproxy 抓包分析登录请求"""

    # 创建配置了抓包代理的 Web 平台客户端
    web = igapi.web.latest.Client(
        proxy=igapi.Proxy.http("127.0.0.1", 8080),
        danger_accept_invalid_certs=True,  # 信任 mitmproxy 证书
        http1_only=True,                   # 兼容 mitmproxy
    )

    try:
        await web.login("你的用户名", "你的密码")
        print("登录成功,请查看 mitmproxy 界面(http://127.0.0.1:8081)")

        # 导出账号信息用于后续复用
        session_str = web.export_account_string()
        with open("session.txt", "w") as f:
            f.write(session_str)
        print("Session 已保存到 session.txt")

    except igapi.TwoFactorRequired:
        code = input("请输入双因素验证码:")
        await web.verify_two_factor(code)
        print("二步验证通过")

    except igapi.ChallengeRequired as e:
        print(f"需要通过验证挑战:{e}")

    except ValueError as e:
        print(f"登录失败:{e}")

    except ConnectionError as e:
        print(f"代理连接失败,请检查 mitmproxy 是否已启动:{e}")


if __name__ == "__main__":
    asyncio.run(analyze_login())

第三步:在浏览器打开 http://127.0.0.1:8081,即可在 mitmproxy Web 界面中看到完整的请求和响应详情。


注意事项

danger_accept_invalid_certs 仅用于调试

此参数会禁用 TLS 证书链校验,使客户端接受任意自签证书。这意味着在中间人攻击下,客户端无法识别伪造的证书。请严格限制在本地开发和调试环境中使用,切勿在生产环境或处理真实用户凭据的场景下开启。

# 正确用法:仅在本地调试时开启
client = igapi.android.latest.Client(
    proxy=igapi.Proxy.http("127.0.0.1", 8080),
    danger_accept_invalid_certs=True,  # 仅调试用
)

# 生产环境:不传此参数,默认为 False
client = igapi.android.latest.Client()

http1_only 的兼容性影响

强制 HTTP/1.1 会关闭连接复用(HTTP/2 多路复用),在高频请求场景下会略微降低吞吐量。建议仅在代理工具不支持 HTTP/2 时开启,正常使用时保持默认值(False)。

代理地址格式

普通 HTTP CONNECT 代理请使用 Proxy.http(...)http:// 前缀,即使目标站点是 HTTPS。Proxy.https(...) / https://proxy-host:port 表示“代理服务器本身使用 TLS”,只有代理服务商明确支持 HTTPS 代理端点时才使用。

Proxy.from_url(...) 会兼容常见代理池格式:host:port 会按 http://host:port 处理,host:port:user:pass 会按 http://user:pass@host:port 处理。

# 普通 HTTP CONNECT 代理
proxy = igapi.Proxy.http("127.0.0.1", 8080)

# 等价写法:自动补为 http://127.0.0.1:8080
proxy = igapi.Proxy.from_url("127.0.0.1:8080")

# 代理池常见格式:自动转为 http://user:pass@proxy.example.com:8080
proxy = igapi.Proxy.from_url("proxy.example.com:8080:user:pass")

常见问题

Q:配置了代理后抛出 ConnectionErrorProxyConnect,该如何排查?

A:请按以下顺序检查:(1) 确认代理软件或代理服务已启动,主机、端口、用户名、密码正确;(2) 普通 HTTP CONNECT 代理请使用 http://,不要因为目标站是 HTTPS 就写成 https://;(3) 确认代理允许 CONNECT 到 www.instagram.com:443;(4) 抓包代理(Charles/mitmproxy)需设置 danger_accept_invalid_certs=True;(5) 代理工具不支持 HTTP/2 时再设置 http1_only=True


Q:没有传 proxy 时会读取系统代理吗?

A:不会。当前版本的 Web 传输层在 proxy=None 时会显式禁用系统代理,不会读取 HTTP_PROXY / HTTPS_PROXY / ALL_PROXY。需要代理时必须显式传入 proxy 参数。


Q:如何验证请求确实经过了代理?

A:在 mitmproxy 界面(http://127.0.0.1:8081)或 Charles 的 Session 列表中,执行一次 API 调用后,应能看到对应的 i.instagram.comwww.instagram.com 请求记录。如果没有记录,说明流量未走代理,请检查 proxy 参数是否正确传入客户端构造函数。


Q:代理需要用户名密码认证,如何配置?

A:在 Proxy 构造函数中传入 usernamepassword

client = igapi.android.latest.Client(
    proxy=igapi.Proxy.http("代理服务器地址", 8080, username="用户名", password="密码"),
    danger_accept_invalid_certs=True,
    http1_only=True,
)

使用 Proxy.http(...)Proxy.socks5h(...) 等对象构造函数时,密码中的 @: 等特殊字符不需要手动 URL 编码。只有使用 Proxy.from_url("http://user:pass@host:port") 解析 URL 字符串时,才需要按 URL 规则编码特殊字符。