使用 Chrome 插件拦截广告的原理 您所在的位置:网站首页 去除网站广告插件 使用 Chrome 插件拦截广告的原理

使用 Chrome 插件拦截广告的原理

2024-02-23 18:18| 来源: 网络整理| 查看: 265

使用 Chrome 插件拦截广告的原理

项目地址:chrome_plugin_zhihu_adblock

本文阅读起来可能需要先了解一些 Chrome 插件基础知识,通过本文您可以学到什么?

chrome 插件拦截广告思考方法和一般原理浏览器拦截 fetch 和 xhr 请求的方法 思路

网页上的广告可以分以下三种情况:

网页上的广告都是由 html 构成的,所以只要用 chrome 插件删除这些 html即可。有些广告是在正常加载后进行动态加载的,它们会和一般的代码块混在一起,这里我们可以拦截代码块的 http 请求,然后在请求成功之后,把广告从 html 上面删去。有些广告是通过专门的 http 请求加载的,这里我们拦截这些 http 请求,让他们发不出去即可。 删除 html

我们只需要知道广告 html 的 selector,然后直接删除即可,这里我们写一个比较通用的函数:

// fuckAd const createFuckAd = (adSelector, textSelector) => () => { // 广告 const ads = document.querySelectorAll(adSelector); if (ads.length > 0) { const cardBrand = document.querySelector(textSelector); if (cardBrand) { console.log(`已屏蔽广告:${cardBrand.innerText}`); } // 删掉广告 [...ads].forEach(item => item.parentNode.removeChild(item)); } }

然后我们在 onload 事件里面删除广告即可。我们以知乎为例,代码如下:

window.onload = () => { createFuckAd('.Pc-card')(); createFuckAd('.Pc-feedAd-container', '.Pc-feedAd-card-brand--bold')(); createFuckAd('.Pc-word-card', '.Pc-word-card-brand-wrapper > span')(); } 拦截请求

对于动态加载的广告,我们可以拦截请求,判断是否有加载广告的请求进来了,然后对于混有正常请求的代码,我们在请求成功之后删掉广告;对于只有广告的请求,我们直接拦截这些请求。这里我们以 fetch 为例(对于 xhr 请求,可以通过这个库Ajax-hook),代码如下:

// hook fetch const fetch_helper = { originalFetch: window.fetch.bind(window), myFetch: function (...args) { // 拦截只有广告的 http 请求 if (args[0].includes('https://www.zhihu.com/commercial_api/')) { return Promise.reject(1); } return fetch_helper.originalFetch(...args).then((response) => { // 对于有正常代码的 http 请求,在请求完成之后,删除广告 if (response.url.startsWith('https://www.zhihu.com/api/v3/feed/topstory/recommend?')) { setTimeout(createFuckAd('.Pc-feedAd-container', '.Pc-feedAd-card-brand--bold'), 188); } return response; }); }, } window.fetch = fetch_helper.myFetch; 其它

核心代码我们已经写完了,然后只需要在document_start的时候引入代码即可。这里需要注意的是,我们不能直接在 contentScript 里面运行上面的代码,因为虽然 contentScript 能够操作页面上的 dom 元素,但是它运行在一个独立的环境里面,这里我们需要使用chrome.runtime.getURL获取 url,然后动态加载:

const s = document.createElement("script"); s.src = chrome.runtime.getURL("main.js"); s.onload = function () { s.parentNode.removeChild(s); }; (document.head || document.documentElement).appendChild(s); 思考

其实上面只是拦截广告的方法,但是对于一个好的广告拦截插件,怎么判断 html 和 js 是一个广告,才真正是一个非常大的挑战,我们通过查看adblock plus的源码可以发现它是这么判断的:

// popupBlocker.js function checkPotentialPopup(tabId, popup) { let url = popup.url || "about:blank"; let documentHost = extractHostFromFrame(popup.sourceFrame); let specificOnly = !!checkWhitelisted( popup.sourcePage, popup.sourceFrame, null, contentTypes.GENERICBLOCK ); let filter = defaultMatcher.matchesAny( parseURL(url), contentTypes.POPUP, documentHost, null, specificOnly ); if (filter instanceof BlockingFilter) browser.tabs.remove(tabId); logRequest( [popup.sourcePage.id], {url, type: "POPUP", docDomain: documentHost, specificOnly}, filter ); }

它首先获取可能的跳转弹窗的 url,然后判断 url 的 host 和当前页面的 host是否一样,再判断白名单里面有没有。当然还有使用tensorflow通过机器学习收集可能的广告 url:

// ml.js const tfCore = require("@tensorflow/tfjs-core"); const tfConverter = require("@tensorflow/tfjs-converter"); for (let object of [tfCore, tfConverter]) { for (let property in object) { if (!Object.prototype.hasOwnProperty.call(tf, property)) tf[property] = object[property]; } }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有