匹配范围
*://flk.npc.gov.cn/*gov-law-recent用途 读取国家法律法规数据库搜索页的最新法规列表,返回页面可见的法规标题、时效状态、公布日期、施行日期、法规类别和制定机关。 执行前提 先打开国家法律法规数据库: https://flk.npc.gov.cn/index.html 页面公开可读,无需登录。脚本会在当前页面主世界把前端路由切换到 /search,等待 .result-item 列表渲染后读取…
*://flk.npc.gov.cn/*dom.read1return await (async () => {2 const input = typeof params === "object" && params !== null ? params : {};3 const limit = readLimit(input.limit, 10, 50);4 5 if (location.hostname !== "flk.npc.gov.cn") {6 throw new Error("请先打开国家法律法规数据库页面:https://flk.npc.gov.cn/index.html");7 }8 9 try {10 sessionStorage.setItem("searchConditions", "");11 localStorage.setItem("halfMonth", "false");12 } catch (error) {13 // Storage can be unavailable in strict browser modes.14 }15 16 await ensureSearchRoute();17 const items = await waitForItems(limit, 12000);18 if (items.length === 0) {19 throw new Error("未读取到法规列表。请确认页面已进入 /search 并完成加载。");20 }21 return items;22 23 async function ensureSearchRoute() {24 if (location.pathname === "/search") {25 return;26 }27 28 history.pushState({}, "", "/search");29 window.dispatchEvent(new PopStateEvent("popstate", { state: history.state }));30 await delay(500);31 }32 33 async function waitForItems(maxItems, timeoutMs) {34 const startedAt = Date.now();35 while (Date.now() - startedAt < timeoutMs) {36 const rows = parseItems(document, maxItems);37 if (rows.length > 0) {38 return rows;39 }40 await delay(300);41 }42 return parseItems(document, maxItems);43 }44 45 function parseItems(root, maxItems) {46 const nodes = Array.from(root.querySelectorAll(".result-item"));47 const rows = [];48 49 for (const node of nodes) {50 const titleNode =51 node.querySelector(".title .title-content") ||52 node.querySelector(".title-content") ||53 node.querySelector(".title");54 const title = cleanText(titleNode ? titleNode.textContent : "");55 if (!title) {56 continue;57 }58 59 const descNodes = Array.from(node.querySelectorAll(".desc div"));60 const descTexts = descNodes.map((item) => cleanText(item.textContent)).filter(Boolean);61 const link = node.querySelector("a[href]");62 63 rows.push({64 index: rows.length + 1,65 title,66 status: cleanText((node.querySelector(".status") || {}).textContent),67 publishDate: fieldValue(descTexts, "公布日期"),68 effectiveDate: fieldValue(descTexts, "施行日期"),69 lawType: cleanText((node.querySelector(".desc .type") || {}).textContent) || descTexts[2] || "",70 authority:71 cleanText((node.querySelector(".desc .department") || {}).textContent) ||72 descTexts[3] ||73 "",74 url: link ? absoluteUrl(link.getAttribute("href"), document.baseURI) : location.href,75 });76 77 if (rows.length >= maxItems) {78 break;79 }80 }81 82 return rows;83 }84 85 function fieldValue(items, label) {86 const item = items.find((value) => value.indexOf(label) >= 0);87 if (!item) {88 return "";89 }90 return cleanText(item.replace(label, "").replace(/^[::]\s*/, ""));91 }92 93 function delay(ms) {94 return new Promise((resolve) => setTimeout(resolve, ms));95 }96 97 function readLimit(value, fallback, max) {98 if (value === undefined || value === null || value === "") {99 return fallback;100 }101 const numberValue = Number(value);102 if (!Number.isInteger(numberValue)) {103 throw new Error("参数 limit 必须是整数。");104 }105 if (numberValue < 1 || numberValue > max) {106 throw new Error("参数 limit 必须在 1 到 " + max + " 之间。");107 }108 return numberValue;109 }110 111 function cleanText(value) {112 return String(value || "").replace(/\s+/g, " ").trim();113 }114 115 function absoluteUrl(value, baseUrl) {116 if (!value) {117 return "";118 }119 try {120 return new URL(String(value), baseUrl).toString();121 } catch (error) {122 return "";123 }124 }125})();