活动启动前,可以自动将 IG 账号列表与简报核对,并生成一份仅包含需要关注记录的 CSV。脚本会逐行请求主页,将用户名、隐私状态和认证状态与预期值比较,同时保存可用的计数器。这样,重复的人工检查就能转变为一个清晰的控制步骤,在活动交付执行前完成。
任务:在发布前发现差异
活动表格通常会列出账号名称和一些预期条件:主页应为公开状态,用户名应与已确认的信息一致,认证标记也应符合简报记录。从名单准备到活动启动期间,账号可能更改名称、转为私密,或者实际对应的是另一个名称相似的主页。如果逐行人工检查,流程就难以复现,也不容易快速筛出异常。

进行此类初步诊断,只需按用户名获取主页。jsonscraper 发布的文档列出了路由 GET /v1/user/by/username,并使用参数 username;此外,还提供可选参数 cache_timeout。响应中可能包含用户名、全名、private 和 verified 标记、帖子数、粉丝数和关注数,以及个人简介。应以实际响应中的字段为准:某个响应样本只能证实这些字段曾出现在观察到的响应中,实际值可能不同,也可能缺失。
准备表格和检查规则
创建一个名为 profiles.csv 的 CSV 文件,包含 username、expected_private 和 expected_verified 列。在后两个字段中填写预期值 true 或 false,用户名则不要带 @ 符号。如果某个主页的预期状态未知,就将对应单元格留空:脚本不应把缺少预期值视为错误。
username,expected_private,expected_verified
examplebrand,false,true
anotheraccount,false,false
这里的检查只处理两个具体问题:收到的用户名是否与请求的用户名一致,以及隐私和认证状态是否与记录的预期相符。计数器和个人简介会作为背景信息保存,供人工评估,而不会被当作受众质量或创作者是否适合该活动的证据。
连接 IG Scraper API
将访问密钥保存在环境变量 JSONSCRAPER_INSTAGRAM_LICENSE_KEY 中。不要把密钥写入 CSV、源代码或运行日志。官方的 IG endpoint 文档说明了路由和参数名称;API 基础地址为 https://ig.jsonscraper.com,密钥参数名为 license_key。
处理完整名单前,先用一条测试记录发起试验请求,检查 JSON 结构,并确认你的账号拥有访问权限。由于此 endpoint 接受用户名,这个简单场景不需要已知主页 ID,也不需要其他路由。
示例:请求、比较并生成异常 CSV
以下脚本兼容 Python 3.8 及以上版本。它会读取 CSV,为每个主页发送一次 GET 请求,检查 HTTP 响应状态,并将重要的原始字段与比较结果一起保存。先运行 python -m pip install requests 安装依赖,再在启动脚本前导出密钥。

import csv
import os
import time
from pathlib import Path
import requests
BASE_URL = "https://ig.jsonscraper.com/v1/user/by/username"
API_KEY = os.environ["JSONSCRAPER_INSTAGRAM_LICENSE_KEY"]
INPUT_FILE = Path("profiles.csv")
OUTPUT_FILE = Path("preflight_results.csv")
def parse_expected(value):
value = (value or "").strip().lower()
if value == "true":
return True
if value == "false":
return False
return None
def profile_from_response(payload):
# The documented observed response wraps profile fields in "ig".
if payload.get("status") != "ok":
raise ValueError("API response status is not ok")
profile = payload.get("ig")
if not isinstance(profile, dict):
raise ValueError("Response has no profile object under 'ig'")
return profile
with INPUT_FILE.open(newline="", encoding="utf-8") as source:
rows = list(csv.DictReader(source))
results = []
for row in rows:
requested = (row.get("username") or "").strip().lstrip("@")
if not requested:
results.append({
"requested_username": "",
"result": "missing_username",
"error": "username is empty",
})
continue
try:
response = requests.get(
BASE_URL,
params={"username": requested, "license_key": API_KEY},
timeout=30,
)
response.raise_for_status()
profile = profile_from_response(response.json())
actual_username = profile.get("username")
actual_private = profile.get("is_private")
actual_verified = profile.get("is_verified")
expected_private = parse_expected(row.get("expected_private"))
expected_verified = parse_expected(row.get("expected_verified"))
checks = []
if actual_username and actual_username.casefold() != requested.casefold():
checks.append("username_mismatch")
if expected_private is not None and actual_private != expected_private:
checks.append("privacy_mismatch")
if expected_verified is not None and actual_verified != expected_verified:
checks.append("verification_mismatch")
results.append({
"requested_username": requested,
"username": actual_username,
"full_name": profile.get("full_name"),
"is_private": actual_private,
"is_verified": actual_verified,
"media_count": profile.get("media_count"),
"follower_count": profile.get("follower_count"),
"following_count": profile.get("following_count"),
"result": "review" if checks else "matched",
"checks": ";".join(checks),
"error": "",
})
except (requests.RequestException, ValueError, KeyError) as exc:
results.append({
"requested_username": requested,
"result": "request_or_response_error",
"error": str(exc),
})
# A small delay spaces requests; it is not a documented quota guarantee.
time.sleep(0.5)
fieldnames = sorted({key for item in results for key in item})
with OUTPUT_FILE.open("w", newline="", encoding="utf-8") as destination:
writer = csv.DictWriter(destination, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(results)
print("Saved", len(results), "rows to", OUTPUT_FILE)
代码会按观察到的响应包装结构进行检查:外层的 status 和主页对象 ig。如果服务提供商更改格式,结构检查会停止处理相应记录并保存错误,而不是悄悄生成错误的匹配结果。脚本不会打印密钥,也不会将密钥写入输出文件。
如何读取结果
在 preflight_results.csv 中,状态为 matched 的记录表示已通过设定的比较。review 表示一个或多个参数与简报不符;checks 列会指出具体差异。请求或响应错误会单独标记,因此数据不可用不会被误认为已确认匹配。
粉丝数和帖子数可以帮助人工查看主页当前状态,并与申请资料对照。这些是请求响应中的瞬时数值。若要评估一段时间内的变化,请保存单独的、带日期的运行结果;单次检查不包含历史记录。字段可能为空,此时记录仍可用于核实身份和检查其他可用特征,但不能用于比较缺失的计数器。
在活动启动前自动化
人工检查过测试 CSV 后,可以将脚本加入定时任务或活动准备步骤。为了确保检查可复现,请单独保存原始名单,记录运行日期,并将结果 CSV 保存到访问受限的工作存储中。如果用户名可能变更,可以使用你自己的系统中的稳定行标识符,以便重新处理。
名单变大时,可增加并发限制,只对临时网络错误重试,并在不包含密钥的情况下单独记录错误代码。不要对无效密钥或格式错误的用户名无限重试。只有符合所需的新鲜度策略时,才添加 cache_timeout:文档指出,IG 默认关闭缓存,大于零的值则会在指定时长内启用缓存。
主页检查可以将人工核对缩减为一份具体的异常清单:在活动启动前,用户名、公开状态、认证状态和可用计数器都汇总在同一张表中。关于 API 参数和当前集成选项,请参阅 IG Scraper API 页面和路由文档。