1 Adblock plus rules
1.1 Filter rules
-
Hardcoded rule,直接写个网址,可以使用wildcasts.
-
exception rules: “
@@http://example.com”,这个网站的所有内容都不
block
-
标记规则的开头和结尾:
|, “swf|”, 匹配结尾是
swf的
url.
-
“abc” 等价于“
*abc*”
-
过滤特定域名的内容:“
||example.com/banner.gif”可以过滤
http://www.example.com/banner.gif,http://example.com/banner.gif,https://example.com/banner.gif.
-
分割符,
^, 可以表示:
Separatorcharacter is anything but a letter, a digit, or one of thefollowing: _-.%. In the following example all separator charactersare shown in red:http:
//
example.com
:
8000
/
foo.bar
?
a
=
12
&
b
=
%D1%82%D0%B5%D1%81%D1%82
-
注释:!
-
Filter options
格式:“规则
$option1,option2”
-
script — external scripts loaded via HTML scripttag
-
image
—regular images, typically loaded via HTML img tag -
stylesheet
—external CSS stylesheet files -
object
—content handled by browser plugins, e.g. Flash or Java -
xmlhttprequest
—requests started by the XMLHttpRequestobject -
object-subrequest
—requests started plugins like Flash -
subdocument
—embedded pages, usually included via HTML frames -
document
—the page itself (only exceptionrules can be applied to the page) -
elemhide
—for exception rules only, similar todocument
but onlydisables elementhiding rules on the page rather than all filter rules -
other
— types of requests not covered inthe list above -
domain restriction, domain=xxx.com|yyy.com, 规则只应用在指定的domain.
-
Third-party 或者first-party: 规则应用于本方或者第三方的资源
-
inversed option: ~option,相当于反义词。
-
规则部分
可以使用正则表达式,但是鉴于效率,最好少用。
1.2 hidding rules
用来隐藏文档中的原素而不是一个独立的可下载资源
-
基本格式
##element_name.class_name 限定元素名和class名
##element_name 只指定元素名
##element_name#id_name 限定元素名和id
##*.class_name 只限定class名
-
指定domain
domain1.com,domain2.com,domain3.com##*.sponsor
可以隐藏多个
domain的
class是
sponsor的元素。
~
domain.com可以屏蔽该
domain
-
通过
attribute选择元素
##table[width="80%"]
##div[title*="adv"] title包含
adv
##div[title^="adv"][title$="ert"]title以
adv开头,以
ert结尾
##table[width="80%"][bgcolor="white"]
-
exception rule
规则
1:
##div.textad
规则
2:
example.com#@#div.textad
上述
2者等价于:
~example.com##div.textad
1.3 如何让一个网站完全不被filter和hidenrules影响
Filter rules可以使用@@example.com
hidden rules:问题是上述靠@@指定的例外规则是否也会阻止hiddenrules.?搭服务器测试一下。
发现过滤规则文件里:
a.jpg并不能在第一次加载时把a.jpg给过滤掉,debug一下。
难道是资源被预加载了?log里发现广告过滤没有起作用。试着写一个简单的abp.txt测试一下原因。
发现,a.jpb被预加载了,说明oracle里面有他的记录。在第一次加载这个网页时,不应该加载他,也不应该把它写入到oracle记录里。看一下。广告过滤的检查和向oracle里面report数据的顺序,按道理说应该是广告过滤在先吧。
结果发现在进行adblock检查之前a.jpb就被加入了oracle。当下回加载网页的时候,就会首先预加载a.jpg,并且因为此时没有document实例,所以也没法对预加载的资源进行adblock检查,于是该资源就被成功加载到memcache里了。当html下载完成后,解析发现需要a.jpg于是又发现memcache里面有,就可以直接使用了,不会走到resourceloader里面,也就不会进行adblock检查了。导致的结果是这个图片被加载了而且被显示出来了。结论:第一次没有预加载数据的情况下加载网页时,应该先进行adblock检查。检查通过的资源,才记录到oracle数据库里。
-
广告过滤触发点:ResourceLoader::start()里
-
保存资源下载记录到oracle的触发点:ResourceFetcher::requestResource(Resource::Typetype, FetchRequest& request)
2 代码分析
2.1 构造规则
每个规则占用一行字符串,拿出来解析,解析的流程:
-
字符串解析得到原始的规则信息
比如是否是exception规则,是否包含domain限制等。最后会得到一个regularexpression,它和其他规则相关的信息可以用于后来的规则匹配。
-
根据domain,shortcuts等信息,把规则分类
domain mapped rules. 该规则对应某domain
Shortcuts mapped rules. 该规则有某关键字
Unmapped rules,剩下的规则
分类的目的在于进行规则检查时尽两减少需要匹配的规则量。查找时间缩短为log级别。使用map
2.2 规则检查
先根据资源的url,domain,shortcuts从所有规则里挑出一些可能相关的规则,然后用着写规则去检查这个资源。
在若干各规则匹配的时候,每个规则检查的结果分三种情况:
passed, 这个规则允许该资源,优先级最高
filtered, 这个规则禁止该资源,还得看是否有规则允许该资源。
NA, 无关的
具体每个规则的匹配流程:
ABPFilterRule::shouldBeFiltered(const KURL& baseUrl, constKURL& rawResourceUrl, ElementType type)
这个函数一步一步判断本规则的某些原则是否可以应用于这个资源地址,判断是有顺序的:
一个规则,可能有自己的限定范围,即只对满足特定要求的网址产生效果,比如他可能只对第三方的网址,或者只对image类型的元素产生作用。那么如果资源网址和网站是同一方的,或者这个资源不是图片,那么就不用再针对这个原则继续分析这个资源。因为这个原则对于这个资源来说没有意义。
-
先判断本规则的firstparty/third party原则是否和这个资源相符,如果本规则应用于thirdparty, 恰巧这个资源是thirdparty资源,那么目前看来是match的。可以继续分析,如果不match,就直接matched= false. 这样函数就返回NA了。
-
然后判断elementtype,image? Css? Script?...
-
然后判断domain的限制,是否必须是某个domain?...
-
最后判断正则表达式是否匹配.
这几个原则,有一个不匹配,那么本原则就无法应用于这个资源。就返回NA,如果本规则可以通过上述检查,那么本规则对这个resource具有影响,要么passed,要么filtered.
2.3 规则检查时机
ResourceFetcher::requestResource()
ResourceLoader::start()
都可以。但是resourceFetcher较前一些,可以提前决定是否过滤。如果需要过滤,那么就可以不用建立resourceLoader.而且也不会把这个资源加入资源预测的数据库里。如果加入了资源预测的数据库里就会导致下一次加载时,会在document建立之前直接预加载应该被过滤掉的资源。所以推荐在ResourceFetcher里加入检查点。