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