匹配范围
*://www.gov.cn/*gov-policy-recent用途 读取中国政府网“最新政策”页面的政策列表,返回标题、发布日期和链接。适合快速查看近期公开政策文件。 执行前提 先打开中国政府网最新政策页面: https://www.gov.cn/zhengce/zuixin/index.htm 页面公开可读,无需登录。脚本优先读取当前页面列表;如果页面列表尚未渲染,会读取同站点公开 JSON 数据。 参数 通过 -…
*://www.gov.cn/*dom.read1return await (async () => {2 const input = typeof params === "object" && params !== null ? params : {};3 const limit = readLimit(input.limit, 10, 50);4 const jsonUrl = "https://www.gov.cn/zhengce/zuixin/ZUIXINZHENGCE.json";5 6 const domRows = parseDomList(document, limit);7 if (domRows.length > 0) {8 return domRows;9 }10 11 const response = await fetch(jsonUrl, { credentials: "include" });12 if (!response.ok) {13 throw new Error("无法读取最新政策数据,HTTP " + response.status + "。");14 }15 16 const data = await response.json();17 if (!Array.isArray(data)) {18 throw new Error("最新政策数据格式不是数组。");19 }20 21 return data22 .map((item) => ({23 title: cleanText(decodeHtml(item && item.TITLE)),24 date: cleanText(item && item.DOCRELPUBTIME),25 url: absoluteUrl(item && item.URL, jsonUrl),26 }))27 .filter((item) => item.title && item.url)28 .slice(0, limit)29 .map((item, index) => ({ index: index + 1, ...item }));30 31 function parseDomList(root, maxItems) {32 const nodes = Array.from(33 root.querySelectorAll(".news_box li, .list li, .list_item, .news-list li")34 );35 const rows = [];36 const seen = new Set();37 38 for (const node of nodes) {39 const link = node.querySelector("a[href]");40 if (!link) {41 continue;42 }43 44 const title = cleanText(link.getAttribute("title") || link.textContent);45 const url = absoluteUrl(link.getAttribute("href"), document.baseURI);46 if (!title || !url) {47 continue;48 }49 50 const key = url + "\n" + title;51 if (seen.has(key)) {52 continue;53 }54 seen.add(key);55 56 const dateNode = node.querySelector(".date, time, .time, .pubtime, .sourceTime");57 const dateText = dateNode ? cleanText(dateNode.textContent) : cleanText(node.textContent);58 rows.push({59 index: rows.length + 1,60 title,61 date: extractDate(dateText),62 url,63 });64 65 if (rows.length >= maxItems) {66 break;67 }68 }69 70 return rows;71 }72 73 function readLimit(value, fallback, max) {74 if (value === undefined || value === null || value === "") {75 return fallback;76 }77 const numberValue = Number(value);78 if (!Number.isInteger(numberValue)) {79 throw new Error("参数 limit 必须是整数。");80 }81 if (numberValue < 1 || numberValue > max) {82 throw new Error("参数 limit 必须在 1 到 " + max + " 之间。");83 }84 return numberValue;85 }86 87 function cleanText(value) {88 return String(value || "").replace(/\s+/g, " ").trim();89 }90 91 function decodeHtml(value) {92 const element = document.createElement("textarea");93 element.innerHTML = String(value || "");94 return element.value;95 }96 97 function absoluteUrl(value, baseUrl) {98 if (!value) {99 return "";100 }101 try {102 return new URL(String(value), baseUrl).toString();103 } catch (error) {104 return "";105 }106 }107 108 function extractDate(value) {109 const text = cleanText(value);110 const match =111 text.match(/\d{4}-\d{1,2}-\d{1,2}/) ||112 text.match(/\d{4}年\d{1,2}月\d{1,2}日/) ||113 text.match(/\d{4}[./]\d{1,2}[./]\d{1,2}/);114 return match ? match[0] : "";115 }116})();