from mitmproxy import http, ctx import json, requests FEED_KEYWORD = "/api/sns/v1/feed" LIKE_URL = "https://edith.xiaohongshu.com/api/sns/v1/like" COMMENT_URL = "https://edith.xiaohongshu.com/api/sns/v1/comment" COLLECT_URL = "https://edith.xiaohongshu.com/api/sns/v1/collect" AUTH_HEADER_KEYS = ["Authorization", "Cookie", "X-Sign"] COMMENT_TEXT = "好喜欢你的作品!" FOLLOWER_THRESHOLD = 1000 session = requests.Session() auth_headers = {} def is_xhs_host(host: str): return host and "xiaohongshu.com" in host def request(flow: http.HTTPFlow): if not is_xhs_host(flow.request.host): # 不打印非小红书请求日志 return # 只处理小红书请求,打印请求日志 ctx.log.info(f"[REQ] {flow.request.method} {flow.request.pretty_url}") updated = False for k in AUTH_HEADER_KEYS: if k in flow.request.headers: val = flow.request.headers[k] if auth_headers.get(k) != val: auth_headers[k] = val updated = True if updated: session.headers.clear() session.headers.update(auth_headers) def response(flow: http.HTTPFlow): if not is_xhs_host(flow.request.host): # 不打印非小红书响应日志 return ctx.log.info(f"[RES] {flow.request.method} {flow.request.pretty_url} - {flow.response.status_code}") if FEED_KEYWORD not in flow.request.pretty_url: return try: data = flow.response.json() except Exception: ctx.log.warn("响应不是 JSON") return posts = extract_posts(data) for post in posts: pid, fans, uid = post["id"], post["fans"], post["user_id"] gender = post.get("gender", "").lower() if fans is not None and fans < FOLLOWER_THRESHOLD and gender in ["f", "female", "女"]: ctx.log.info(f"目标帖子: {pid}, 粉丝 {fans}, 性别 {gender}") do_like(pid) do_comment(pid) do_collect(pid) def extract_posts(data): results = [] items = data.get("data", {}).get("items", []) for item in items: try: pid = item["id"] fans = item["user"]["fans"] uid = item["user"]["id"] gender = item["user"].get("gender", "") results.append({"id": pid, "fans": fans, "user_id": uid, "gender": gender}) except Exception as e: ctx.log.warn(f"解析帖子出错: {e}") continue return results def do_like(pid): try: r = session.post(LIKE_URL, json={"note_id": pid, "action": "like"}) ctx.log.info(f"点赞 {pid}: {r.status_code} {r.text[:50]}") except Exception as e: ctx.log.warn(f"点赞失败 {pid}: {e}") def do_comment(pid): try: r = session.post(COMMENT_URL, json={"note_id": pid, "content": COMMENT_TEXT}) ctx.log.info(f"评论 {pid}: {r.status_code} {r.text[:50]}") except Exception as e: ctx.log.warn(f"评论失败 {pid}: {e}") def do_collect(pid): try: r = session.post(COLLECT_URL, json={"note_id": pid, "action": "collect"}) ctx.log.info(f"收藏 {pid}: {r.status_code} {r.text[:50]}") except Exception as e: ctx.log.warn(f"收藏失败 {pid}: {e}")