AlexMelanFromRingo/insta_parser

GitHub: AlexMelanFromRingo/insta_parser

一个用 Rust 编写的 Instagram 资料解析器,通过模拟网页端私有 API 调用来下载指定账号的头像、帖子和快拍。

Stars: 0 | Forks: 0

# insta_parser 使用 Rust 编写的 Instagram 个人资料解析工具:支持获取指定账号的头像、帖子(照片/视频,包括轮播图)以及快拍。已经过实际真机测试,确认可正常运行。 Instagram 并未提供稳定的 API,并且会定期更改其端点/请求头。因此,该工具并未采用解析 HTML 页面的方式(这种方式早已失效),而是通过用户自己的账号进行登录,并直接访问 instagram.com 网页前端所调用的相同 JSON 端点。 ## 功能 - 使用账号/密码登录(采用与 instagram.com 网页版相同的机制,包括 2FA 处理)。 - 获取高清 (HD) 个人资料头像。 - 获取帖子流:照片和视频,包括**轮播图**(单个帖子中包含多个附件)——每个附件都会保存为独立的文件。 - 获取个人资料的有效(当前)快拍。 - 支持 Instagram 算法更新后的适配:所有的主机/请求头/端点都集中在一个文件 (`src/client.rs`) 中,只需在该处进行针对性修改即可。 ## 使用方法 ``` echo "login:password" > account.txt # аккаунт, от имени которого будет идти парсинг cargo run --release -- ``` 要求 `PATH` 中已安装 `curl`(详情参见下文的“传输层”章节)。 选项: | 标志 | 描述 | |---|---| | `--out ` | 媒体文件的保存路径(默认为 `downloads/`) | | `--account-file ` | 包含 `login:password` 的文件(默认为 `account.txt`) | | `--two-factor-code ` | 2FA 验证码(如果已知);否则工具会以交互方式提示输入 | | `--count ` | 获取最近帖子的数量(默认为 12) | | `--no-posts` | 不下载帖子 | | `--no-stories` | 不下载快拍 | 输出示例: ``` downloads// ├── avatar.jpg ├── posts/ │ └── _[_].{jpg,mp4} └── stories/ └── _.{jpg,mp4} ``` ## 实现原理 1. **登录** — 通过 `POST /accounts/login/ajax/` 发送匿名会话获取的 CSRF token,密码格式为 `#PWD_INSTAGRAM_BROWSER:0::`(这与浏览器自身的处理方式相同——未使用 RSA 封装,该机制仅供移动端应用使用)。如果返回 `two_factor_required`,工具会提示输入验证码,并通过 `/accounts/login/ajax/two_factor/` 重新进行登录。 2. **个人资料** — 通过 `GET /api/v1/users/web_profile_info/?username=...` 获取用户 ID、头像 (`profile_pic_url_hd`) 以及私密状态。该端点返回的帖子列表会被忽略——因为在实际测试中,`edge_owner_to_timeline_media.edges` 稳定返回为空(已验证,包括使用自身会话访问自己的私密账号),Instagram 似乎已将该接口的响应与帖子流进行了剥离。 3. **帖子** — 作为替代方案,使用 `GET /api/v1/feed/user/{user_id}/?count=N`:该接口会直接返回带有媒体直链 (`image_versions2`/`video_versions`) 的帖子,包括轮播图(`media_type == 8` → 对应 `carousel_media` 数组,其中每个元素都有自己的 `media_type`/媒体内容)。因此无需额外发起请求来解析视频链接。 4. **快拍** — 通过 `GET /api/v1/feed/reels_media/?reel_ids=` 获取,前提是当前会话具有查看该账号快拍的权限(公开资料或当前账号已关注该用户)。 所有的请求都会携带已授权用户的会话 cookie 以及 `X-IG-App-ID` 请求头(instagram.com 网页端的公开 ID),而不是通过独立的移动端签名协议——这正是浏览器自身所采用的访问路径。 ## 传输层:为什么使用 curl 而不是 reqwest 在开发过程中发现,Instagram 的 edge/WAF 会针对通过 `reqwest`/`hyper` 发送的 JSON 端点请求(如 `web_profile_info` 等)稳定返回空白的 `429` 状态码——然而,在相同环境下,使用 `curl` 重放**完全相同的请求**(相同的 cookie、相同的请求头、相同的 URL)却能得到 `200` 响应。我们尝试了多种方案均无济于事:更换 TLS 后端 (`native-tls`/OpenSSL ↔ `rustls`)、强制使用 HTTP/1.1、完全绕过 `reqwest` 内置的 cookie jar 改为手动管理 cookie。这似乎是由于 `hyper` 在 HTTP/2 协议栈层面的传输层指纹识别所致,而 `curl` 则不会触发此机制。 因此,整个网络层 (`src/transport.rs`) 都是基于系统 `curl` 作为子进程运行的封装:cookie 以 Netscape 格式存储在文件中 (`curl -b/-c`),相关的值会直接从该文件中读取(用于填充 `X-CSRFToken` 请求头中的 `csrftoken`),响应体和响应头则通过 `curl -s -i` 进行解析。对于媒体文件本身的下载(CDN 链接),则采用了带有 `-L --fail` 参数的独立处理逻辑,因为视频通常通过重定向提供,而在 JSON 请求中同时使用 `-L` 和 `-i` 会导致解析失败(连续出现多个响应头块,每次跳转对应一个)。 如果将来 `curl` 也开始收到 `429` 响应——这很可能意味着 Instagram 进一步收紧了指纹识别策略(TLS ClientHello/JA3),届时可能需要考虑使用 `curl-impersonate` 或类似能够精准模拟浏览器 TLS 指纹的工具。 ## 如果 Instagram 导致程序失效 Instagram 会不定期更改响应的结构、必需的请求头或路径。如果请求开始返回 401/403/429 或异常的 JSON 数据: 1. 在普通浏览器中打开 profile/story,通过 DevTools → Network 面板找到对应的 XHR 请求。 2. 将请求路径、请求头和请求体与 `src/client.rs` 中的代码进行比对。 3. 修正相关的常量 (`IG_APP_ID`、路径、请求头)——所有的请求逻辑都集中在这一个文件中。 另外请注意:短时间内使用同一账号进行多次连续登录,正是 Instagram 识别自动化行为的典型特征。这可能导致其直接静默拒绝有效的密码(返回 `authenticated: false` 且无明显原因),或者要求进行验证。在调试时,请勿在循环中频繁触发登录。 ## 免责声明 本工具通过用户自身的账号进行授权登录,旨在用于备份用户自己的内容以及该账号有权访问的公开资料。请在符合 Instagram 服务条款及适用法律法规的前提下使用;本工具不适用于大规模/匿名抓取他人的私密数据。
标签:BeEF, Instagram, Rust, URL抓取, 可视化界面, 媒体下载, 数据抓取, 爬虫, 网络流量审计, 通知系统