import { $$, DOMUtils, httpx, log, utils } from "@/env"; import { addBlockCSSWithEnd, addStyleWithEnd } from "@components/env.base"; import { Panel } from "@components/setting/panel"; export const BaiduSearchResult = { init() { Panel.execMenuOnce( [ "baidu-search-optimizationResult-enable", "baidu-search-optimizationResult-removeAds", "baidu-search-optimizationResult-redirect", "baidu-search-optimizationResult-addFavicon", "baidu-search-optimizationResult-markUnsafeLink", ], (config) => { const [enable, removeAds, redirect, addFavicon, markUnsafeLink] = config.value; if (!enable) return; if (!removeAds && !redirect && !addFavicon && !markUnsafeLink) return; return this.searchResultOptimization({ removeAds, redirect, addFavicon, markUnsafeLink }); } ); }, /** * 搜索结果优化 */ searchResultOptimization(config: { removeAds: boolean; redirect: boolean; addFavicon: boolean; markUnsafeLink: boolean; }) { log.info(`搜索结果优化`, config); /** * 判断是否是百度的中转重定向链接 * * + http://www.baidu.com/link?url=xxxx * @param url */ const isDirectUrl = (url: string) => { try { const urlInst = new URL(url); if (urlInst.hostname === "www.baidu.com" && urlInst.pathname === "/link" && urlInst.searchParams.has("url")) { return true; } } catch {} return false; }; const lockFn = new utils.LockFunction(() => { const $results = $$("#content_left > div:not([data-hijack])"); $results.forEach(async ($result) => { if (config.removeAds && DOMUtils.selector('.se_st_footer:contains("广告")', $result)) { // 移除广告 $result.remove(); return; } /** 标题 */ const $title = $result.querySelector("a.sc-link[href]") || $result.querySelector(".c-title a[href]") || $result.querySelector("a.cosc-title-a[href]") || $result.querySelector('[class*="c-line-"] > a[href][class^="title_"]'); if (!$title) return; /** 真实链接,但有时候这个链接是错误的链接,需要处理一下 */ const mu = $result.getAttribute("mu"); const realLinkList: string[] = []; if (typeof mu === "string") { realLinkList.push(mu); } /** 举报的网站 - 一般这里也能获取到真实链接 */ const $feedback = $result.querySelector(".cosc-feedback[data-feedback]"); const feedbackStr = $feedback?.getAttribute("data-feedback"); if (feedbackStr) { const feedback = utils.toJSON(feedbackStr); if (typeof feedback.url === "string") { realLinkList.push(feedback.url); } } let realLink = realLinkList.find((link) => { try { const linkInst = new URL(link); if (linkInst.hostname === "nourl.ubs.baidu.com" || linkInst.hostname.endsWith(".lightapp.baidu.com")) { return; } if (isDirectUrl(link)) { return; } } catch {} return link; }); const titleUrl = $title.getAttribute("href")!.trim(); if (!realLink) { // 依旧没有获取到真实链接 // 使用get请求获取 const requestAttr = "data-direct-http-request-ing"; if ($title.hasAttribute(requestAttr)) { // ignore return; } else if (isDirectUrl(titleUrl)) { // 百度中转链接 // 主动请求获取重定向的链接 $title.setAttribute(requestAttr, "true"); const response = await httpx.get(titleUrl, { fetch: false, allowInterceptConfig: false, }); $title.removeAttribute(requestAttr); if (!response.status) return; const finalUrl = response.data.finalUrl; if (isDirectUrl(finalUrl)) return; realLink = finalUrl; $title.setAttribute("data-request-final-url", "true"); } else { return; } } $result.setAttribute("data-hijack", "true"); // 下面是在获取到真实链接后才能添加的功能 if (config.redirect) { // 重定向 $title.href = realLink; $result.setAttribute("data-before-url", titleUrl); } if (config.addFavicon) { // 在前面添加图标 const $ico = DOMUtils.createElement("img"); $ico.className = "website-ico"; try { const realLinkInst = new URL(realLink); $ico.src = `${realLinkInst.origin}/favicon.ico`; DOMUtils.prepend($title, $ico); DOMUtils.css($title, { display: "flex", "align-items": "center", }); DOMUtils.on($ico, "error", () => { $ico.remove(); }); } catch {} } if (config.markUnsafeLink) { // 显示不安全的链接 if (realLink.startsWith("http://")) { DOMUtils.prepend( $title, /*html*/ ` ` ); DOMUtils.css($title, { color: "#ecb3b3 !important", "text-decoration": "line-through !important", }); } } }); }); const observer = utils.mutationObserver(document, { config: { subtree: true, childList: true, attributes: true, }, immediate: true, callback: () => { lockFn.run(); }, }); return [ addStyleWithEnd(/*css*/ ` img.website-ico{ width: 1em; height: 1em; object-fit: contain; margin-right: 4px; } #content_left a.sc-link:has(img.website-ico){ display: inline-flex !important; } `), () => { observer.disconnect(); }, config.removeAds ? addBlockCSSWithEnd("#content_left > div:has(.ec-tuiguang)", "#content_left > div:has(.c-recomm-wrap)") : null, ]; }, };