灵猴市集Linghou Market

微信文章搜索

微信文章weixin-article-search

用途 通过搜狗微信搜索公开微信文章,返回文章标题、链接、摘要和发布时间。适合在浏览器环境中做轻量检索,不抓取正文。 执行前提 需要浏览器能访问 https://weixin.sogou.com/。搜狗微信可能因访问频率、地区、Cookie 状态或风控策略要求验证码;出现验证码或安全验证时,脚本会报错并提示先在浏览器页面完成人机验证后重试。 参数 query…

搜索文章公开读取
版本1.0.0
扫描passed
更新2026-06-28
超时30000ms

匹配范围

*://weixin.sogou.com/*

排除范围

未声明

能力声明

dom.read

代码

源码已展开
1return await (async () => {2  const input = typeof params === "object" && params ? params : {};3  const query = String(input.query || "").trim();4  if (!query) {5    throw new Error("缺少参数 query:请输入要搜索的微信文章关键词。");6  }7 8  const toPositiveInteger = (value, fallback, max) => {9    if (value === undefined || value === null || value === "") return fallback;10    const text = String(value).trim();11    if (!/^\d+$/.test(text)) {12      throw new Error(`参数必须是正整数:${text}`);13    }14    const parsed = Number(text);15    if (!Number.isSafeInteger(parsed) || parsed < 1 || (max && parsed > max)) {16      throw new Error(`参数超出范围:${text}`);17    }18    return parsed;19  };20 21  const page = toPositiveInteger(input.page, 1, 100);22  const limit = toPositiveInteger(input.limit, 10, 10);23  const clean = (value) =>24    String(value || "")25      .replace(/\s+/g, " ")26      .replace(/<!--red_beg-->|<!--red_end-->/g, "")27      .replace(/document\.write\(timeConvert\('\d+'\)\)/g, "")28      .trim();29  const absolutize = (href, base) => {30    if (!href) return "";31    try {32      return new URL(href, base).toString();33    } catch {34      return String(href || "");35    }36  };37 38  const searchUrl = new URL("https://weixin.sogou.com/weixin");39  searchUrl.searchParams.set("query", query);40  searchUrl.searchParams.set("type", "2");41  searchUrl.searchParams.set("page", String(page));42  searchUrl.searchParams.set("ie", "utf8");43 44  const response = await fetch(searchUrl.toString(), {45    method: "GET",46    credentials: "include",47    headers: {48      Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",49    },50  });51  if (!response.ok) {52    throw new Error(`搜狗微信搜索请求失败:HTTP ${response.status}。可能是访问频率过高、验证码或站点策略变化。`);53  }54 55  const html = await response.text();56  const doc = new DOMParser().parseFromString(html, "text/html");57  const bodyText = clean(doc.body && doc.body.innerText);58  if (/验证码|安全验证|异常访问|访问过于频繁|请输入验证码/.test(bodyText)) {59    throw new Error("搜狗微信要求验证码或安全验证。请在浏览器打开 weixin.sogou.com 完成人机验证后重试。");60  }61 62  const cards = Array.from(doc.querySelectorAll(".news-list li"));63  const extracted = cards.map((item) => {64    const linkEl = item.querySelector("h3 a[href]");65    const summaryEl = item.querySelector("p.txt-info");66    const timeEl = item.querySelector(".s-p .s2");67    return {68      title: clean(linkEl && linkEl.textContent),69      url: absolutize(linkEl && linkEl.getAttribute("href"), searchUrl.toString()),70      summary: clean(summaryEl && summaryEl.textContent),71      publish_time: clean(timeEl && timeEl.textContent),72    };73  });74  const rows = extracted.filter((row) => row.title && row.url);75  const empty =76    /没有找到相关的微信文章|未找到相关|暂无相关|没有找到/.test(bodyText) ||77    Boolean(doc.querySelector(".no-result, .no_result, .s-noresult"));78 79  if (extracted.length !== rows.length) {80    throw new Error("搜狗微信返回了缺少标题或链接的结果卡片,页面结构可能已变化,已拒绝返回不完整结果。");81  }82  if (rows.length === 0 && empty) {83    return [];84  }85  if (rows.length === 0) {86    throw new Error("未能识别搜狗微信文章结果。可能是页面结构、验证码或接口策略发生变化。");87  }88 89  return rows.slice(0, limit).map((row, index) => ({90    rank: (page - 1) * 10 + index + 1,91    page,92    title: row.title,93    url: row.url,94    summary: row.summary,95    publish_time: row.publish_time,96  }));97})();