灵猴市集Linghou Market

即刻话题帖子列表

即刻jike-topic-posts

用途 读取即刻移动公开话题页的 SSR 数据,提取话题标题和帖子列表,适合快速查看公开话题中的最新帖子摘要。 执行前提 在 https://m.okjike.com/* 页面执行。当前页是目标话题页时会直接读取页面内的 #_NEXTDATA_;如果传入 topicid 或 topicId,脚本会请求对应公开话题页并解析 HTML。 脚本只读取公开页面已经下…

话题帖子公开读取
版本1.0.0
扫描passed
更新2026-06-28
超时30000ms

匹配范围

*://m.okjike.com/*

排除范围

未声明

能力声明

dom.read

代码

源码已展开
1return await (async () => {2  const input = typeof params === "object" && params ? params : {};3  const current = new URL(location.href);4  const pickedTopicId = input.topic_id || input.topicId || "";5  const urlTopicId = (current.pathname.match(/^\/topics\/([^/?#]+)/) || [])[1] || "";6  const topicId = String(pickedTopicId || urlTopicId).trim();7  const limitValue = Number(input.limit ?? 20);8  const limit = Math.max(1, Math.min(50, Number.isFinite(limitValue) ? Math.floor(limitValue) : 20));9 10  if (!topicId) {11    throw new Error("未提供 topic_id,且当前页面不是即刻话题页。请打开 /topics/<topic_id> 或传入 topic_id。");12  }13 14  const targetUrl = `https://m.okjike.com/topics/${encodeURIComponent(topicId)}`;15  const canUseCurrentPage = current.origin === "https://m.okjike.com" && urlTopicId === topicId;16 17  const getNextDataFromDoc = (doc) => {18    const node = doc.querySelector("script#__NEXT_DATA__");19    if (!node || !node.textContent) return null;20    try {21      return JSON.parse(node.textContent);22    } catch (error) {23      throw new Error(`公开页 SSR 数据解析失败:${error.message}`);24    }25  };26 27  const loadNextData = async () => {28    if (canUseCurrentPage) {29      const currentData = getNextDataFromDoc(document);30      if (currentData) return currentData;31    }32 33    const response = await fetch(targetUrl, {34      credentials: "include",35      headers: { accept: "text/html,application/xhtml+xml" },36    });37    if (!response.ok) {38      throw new Error(`话题公开页读取失败:HTTP ${response.status}。页面可能不存在、需要登录或被站点限制。`);39    }40    const html = await response.text();41    const doc = new DOMParser().parseFromString(html, "text/html");42    const fetchedData = getNextDataFromDoc(doc);43    if (!fetchedData) {44      throw new Error("话题公开页没有可读取的 SSR 数据。页面可能改版、需要登录或仅在客户端加载。");45    }46    return fetchedData;47  };48 49  const compactText = (value) => {50    if (value == null) return "";51    return String(value).replace(/\s+/g, " ").trim();52  };53 54  const authorOf = (user) => {55    if (!user || typeof user !== "object") return null;56    return {57      id: user.id || user.userId || "",58      username: user.username || "",59      name: user.screenName || user.nickname || user.name || "",60      bio: user.briefIntro || "",61    };62  };63 64  const linkOf = (post) => {65    if (!post || !post.id) return "";66    const type = String(post.type || "").toUpperCase();67    const segment = type === "REPOST" ? "reposts" : "originalPosts";68    return `https://m.okjike.com/${segment}/${encodeURIComponent(post.id)}`;69  };70 71  const data = await loadNextData();72  const pageProps = data && data.props && data.props.pageProps ? data.props.pageProps : {};73  const topic = pageProps.topic || {};74  const posts = Array.isArray(pageProps.posts) ? pageProps.posts : [];75 76  if (!topic.id && !posts.length) {77    throw new Error("未在公开页 SSR 数据中找到话题或帖子列表。页面可能改版、需要登录或当前话题没有公开内容。");78  }79 80  const items = posts.slice(0, limit).map((post, index) => ({81    rank: index + 1,82    id: post.id || "",83    author: authorOf(post.user),84    content: compactText(post.content),85    likes: Number(post.likeCount || 0),86    comments: Number(post.commentCount || 0),87    time: post.createdAt || "",88    url: linkOf(post),89  }));90 91  return {92    topic_id: topic.id || topicId,93    topic_title: topic.content || topic.title || topic.messagePrefix || "",94    count: items.length,95    posts: items,96  };97})();