iOS9 新 API 实现广告拦截(Safari Content Blocking)

iOSiBcker • 于 2015-11-06 10:44:38 +0800 • 最后由 dugege2016-04-29 01:28:25 +0800 4980 阅读

Safari-Content-Blocking

阅读本部分内容,我默认你已经有了一定的开发能力,并已经知道iOS Extension概念和广告拦截的意义和了解Xcode的使用和基本的CSS\HMTL概念

iOS9 带来了很多新API,其中一项比较有意思的就是Safari的内容拦截功能Content Blocking Safari Extensions,本文来简单探讨一下Safari内容拦截扩展的使用。

以前我们在iPhone上用safari上网,一直没办法像电脑上一样通过装AdBlock等插件去掉(除非越狱)。所以造成了上网体验的下降,其实我也知道很多网站靠广告费支撑,我并不反对健康的广告,不过有些网站的广告确实多到让人没法忍了··

iOS9带来了Content Blocking Safari Extensions

Content Blocking Safari Extensions,也就是内容拦截,既然能拦截内容,那么拦截广告当然就成为了可能。 下面是官方文档的说明,我稍稍翻译了一下,原文可以点What's New in Safari

新的Safari带来了内容拦截扩展的支持,可以拦截包括cookies,images,resources, pop-ups和其他内容

你的内容拦截扩展负责提供一个JSON文件给Safari,这个JSON文件包含了一个规则(触发器和行为)用于拦截指定的内容,Safari转换这个JSON文件为字节码,不仅能有高效工作并且不会泄露用户的浏览记录。

Xcode包含了一个Blocker App Extension的模板帮助你创建这个JSON文件。你只要编辑模板里的这个JSON文件并提供你需要的触发器和行为就完事了~

接下来官方给出了一个JSON文件的例子

[ { "action": { "type": "block" }, "trigger": { "url-filter": "webkit.org/images/icon-gold.png" } }, { "action": { "selector": "a[href^=\"http://nightly.webkit.org/\"]", "type": "css-display-none" }, "trigger": { "url-filter": ".*" } } ]

好了,官方文档讲完了,比较粗糙,相信看到这里你也和我当初一样一头雾水,这都啥子和啥子啊···

讲解部分

首先,Content Blocking Safari Extensions也是iOS Extensions的一部分(没基础的同学请先移步App Extension Programming Guide),构建方法也是一个APP包含着一个Extensions,所以我们先新建一个demo,然后增加一个Content Blocker Extensions

file

然后我们就会得到一个Extensions对应的Target,并且包含了示例代码和规则demo

``` import UIKit import MobileCoreServices

class ActionRequestHandler: NSObject, NSExtensionRequestHandling {

func beginRequestWithExtensionContext(context: NSExtensionContext) {
    let attachment = NSItemProvider(contentsOfURL: NSBundle.mainBundle().URLForResource("blockerList", withExtension: "json"))!

    let item = NSExtensionItem()
    item.attachments = [attachment]

    context.completeRequestReturningItems([item], completionHandler: nil);
}

} ```

其中demo里的blockerList.json就是苹果给我们的示例规则。

blockerList.json讲解

iOS9中的内容过滤,提供了两种可用行为,blockcss-display-none

  1. block ,拦截不需要的资源,例如广告图片
  2. css-display-none ,隐藏元素,例如隐藏广告banner

block

1.url-filter

url-filter为唯一必选项目,用于匹配url并支持正则表达式

以下是常用的几个

  1. 可选项,用:?

    匹配协议是http或者https
    "url-filter": "https?://baidu.com"

  2. 分组,用:()配合:?

    匹配http://baidu.com 或者http://www.baidu.com
    "url-filter": "http://(www.)?baidu.com"

  3. 匹配任何,用:.

    匹配ad开头的网址
    "url-filter": "http://ad.*"

  4. 匹配个数:* ? +

    分别表示任意,一个或没有,一个以上

  5. 匹配区间:[1-9]

    "url-filter": "http://[1-9].baidu.com"

其他的可以看下正则表达式用法,值得注意的是,因为正则表达式里.表示任意,所以以下两个表达并不相同

"url-filter": "http://baidu.com"
"url-filter": "http://baidu\.com"

2.url-filter-is-case-sensitive

可选,布尔值,用于指定url-filter是否区分大小写

3.resource-type

可选,数组,有指定资源类型,以下值供选择,如果不指定,会匹配所有类型

  • “document”
  • “image”
  • “style-sheet”
  • “script”
  • “font”
  • “raw” (any untyped load, like XMLHttpRequest)
  • “svg-document”
  • “media”
  • “popup”

4.load-type

可选,数组,指定配了的资源和页面在不在一个域下面

  • “first-party”
  • “third-party”

5.if-domain / unless-domain

可选,数组,指定匹配域名


css-display-none

除了上面讲到的,css-display-none下有一个特殊的属性:selector,用于选择需要的document元素,例如

"action": { "type": "css-display-none", "selector": "#newsletter, :matches(.main-page, .article) .annoying-overlay" }

关于css selecter,用处及其强大,还是直接移步这里看吧CSS Selectors Level 4

有了以上基础,基本就能写个demo了 例如我们要写个过滤v2ex手机版广告的的css 可以用以下规则

[ { "action": { "type": "block" }, "trigger": { "if-domain": ["cdn.v2ex.co"], "url-filter": "assets/sidebar/*.png" } }, { "action": { "type": "block" }, "trigger": { "if-domain": ["cdn.v2ex.co"], "url-filter": "assets/sidebar/*.gif" } }, { "action": { "type": "block" }, "trigger": { "if-domain": ["*.v2ex.com","v2ex.com"], "url-filter": "assets/sidebar/.*", "resource-type": ["image", "style-sheet"] } }, { "action": { "type": "css-display-none", "selector": "#Wrapper>.content>div:last-child>.inner>:not(form)" }, "trigger": { "url-filter": ".*" } }, { "action": { "type": "block" }, "trigger": { "url-filter": "adsbygoogle\\.js", "load-type": ["third-party"] } }, { "action": { "type": "css-display-none", "selector": ".adsbygoogle" }, "trigger": { "url-filter": ".*" } } ]

注意:测试记得把safari设置项里内容拦截器设置为你的APP的。每次修改后也不会自动生效,如果想生效,可以关闭内容拦截器再打开,或者用SFContentBlockerManager.reloadContentBlockerWithIdentifier进行reload

实现前后对比

file

关于如何调试

调试selecter

selecter的调试我觉得比较好的办法是浏览器控制台里借用jquery选择器来调试,例如例如$('#Wrapper>.content')即选择ID为Wrapper下面的content class的元素。

调试safari

在系统设置中,选safari并开启高级中的web查看器,可以在电脑上用已经打开开发模式的safari直接查看DOM结构,如 debug-safari

参考
WhatsNewInSafari
Introduction to WebKit Content Blockers
safari-content-blocking-ios9

回复: 2
  • Bison 2016-03-14 18:54:49 +0800

    大神啊 ,👍

  • dugege 2016-04-29 01:28:25 +0800

    test

  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,见 Emoji cheat sheet
  • @name 会链接到用户页面,并会通知他
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
Ctrl+Enter