匹配范围
*://finance.sina.com.cn/roll*sinafinance-rolling-news新浪财经滚动新闻提取 用途 读取新浪财经滚动新闻页中已经渲染出的新闻列表,返回栏目、标题、时间和新闻地址。 执行前提 先打开 https://finance.sina.com.cn/roll/#pageid=384&lid=2519 滚动新闻页,再执行脚本。页面公开可访问,通常无需登录;新闻列表可能由页面脚本异步填充,若页面显示验证、加载失败或列表为空,脚…
*://finance.sina.com.cn/roll*dom.read1const rawParams = params && typeof params === "object" ? params : {};2 3function integerParam(name, fallback, min, max) {4 const raw = rawParams[name];5 const value = raw === undefined || raw === null || raw === "" ? fallback : Number(raw);6 if (!Number.isInteger(value) || value < min || value > max) {7 throw new Error(`${name} must be an integer between ${min} and ${max}`);8 }9 return value;10}11 12function sleep(ms) {13 return new Promise(resolve => setTimeout(resolve, ms));14}15 16function normalizeText(value) {17 return (value || "").replace(/\s+/g, " ").trim();18}19 20function assertRollingNewsPage() {21 const current = new URL(location.href);22 if (current.hostname !== "finance.sina.com.cn" || !current.pathname.startsWith("/roll")) {23 throw new Error("Open https://finance.sina.com.cn/roll/#pageid=384&lid=2519 first, then run this script");24 }25}26 27function detectBlockedPage(doc) {28 const text = normalizeText(`${doc.title || ""} ${doc.body ? doc.body.innerText : ""}`).slice(0, 5000);29 if (/安全验证|验证码|人机验证|访问异常|请输入验证码|访问受限|页面加载失败/.test(text)) {30 return "The page is showing a verification or access-control challenge";31 }32 return "";33}34 35function trustedUrl(raw) {36 if (!raw) return "";37 try {38 const url = new URL(raw, location.href);39 if (url.protocol !== "http:" && url.protocol !== "https:") return "";40 return url.toString();41 } catch {42 return "";43 }44}45 46function extractNews(doc, limit) {47 const rows = [];48 const items = doc.querySelectorAll(".d_list_txt li, #d_list li");49 50 for (const el of items) {51 if (rows.length >= limit) break;52 const titleEl = el.querySelector(".c_tit a") || el.querySelector("a[href]");53 const title = normalizeText(titleEl ? titleEl.textContent : "");54 const url = trustedUrl(titleEl ? titleEl.getAttribute("href") || titleEl.href : "");55 if (!title || !url) continue;56 57 rows.push({58 rank: rows.length + 1,59 column: normalizeText(el.querySelector(".c_chl")?.textContent || ""),60 title,61 date: normalizeText(el.querySelector(".c_time")?.textContent || ""),62 url,63 });64 }65 66 return rows;67}68 69async function waitForNews(doc, limit) {70 const deadline = Date.now() + 10000;71 let rows = extractNews(doc, limit);72 while (Date.now() < deadline && rows.length === 0) {73 const blocked = detectBlockedPage(doc);74 if (blocked) throw new Error(`${blocked}; complete it in the browser and run again`);75 await sleep(250);76 rows = extractNews(doc, limit);77 }78 return rows;79}80 81const limit = integerParam("limit", 20, 1, 100);82assertRollingNewsPage();83 84const blocked = detectBlockedPage(document);85if (blocked) throw new Error(`${blocked}; complete it in the browser and run again`);86 87const items = await waitForNews(document, limit);88if (items.length === 0) {89 throw new Error("No rolling news rows found; the page may be empty, still loading, blocked, or its structure changed");90}91 92return items.slice(0, limit);