kmc
kmc
管理员
管理员
  • UID165
  • 注册日期2004-11-25
  • 最后登录2022-09-22
  • 发帖数9186
  • 经验397枚
  • 威望1点
  • 贡献值124点
  • 好评度41点
  • 忠实会员
  • 终身成就
  • 社区居民
阅读:65391回复:51

AdBlock正则表达式实践心得[by kmc](2005/12/16附件更新)

楼主#
更多 发布于:2004-11-30 00:19
首先,我尚且不懂javascript,以下心得,完全是通过学习正则表达式的文档和实践得出,
写该文的目的之一也是试图消除大家对正则表达式的畏惧心理,从简单之处先入门。
而这其中必定有贻笑大方之处,恳请高手们斧正!


在看本文之前,我在附件中附上了带我进入正则表达式之门的一个基础教程,
和一个“正则表达式的练习器”,建议大家先读此文并粗略的实践一下,因为
下面的文字都站在这篇文章的基础上。

---------------------------------------------------------------------------------------------



通过对正则表达式的文档的研究,以及对本人Maxthon积累下来的广告过滤条目对应的url的分析,
我有以下几点心得:
1.正则表达式的优势,在于高整合度和高精确度,记做到了代码的简洁,又疏而不漏,唯一的缺点,不过是
可读性略差了一点。
2.理论上说,所有的过滤条目都可以用|符号整合到一条正则表达式过滤器里面去,可是这样既雪上加霜地降低了
可读性,还不可避免地失去了正则表达式高整合度的优势。所以,为了能写出好的正则表达式,分析需要匹配的
文本(在这里就是url了)是必不可少的。

*************************************************************************************
我们常见的url无非是:aaa.bbb.ccc/123456789/........htm,gif等等
需要过滤的地址,由抽象到具体来说,往往有以下特点:

I.全部过滤一个不漏,只要出现就喀嚓,往往是令人深恶痛绝的url。
例(例子中都是用原始的带通配符的表达式):*.ad.*;  */ad/*;  *.3721.*/*或者*3721*
II.过滤网址主体,也就是第一个/号之前的所有。
例:www.1000downloads.com/*;    <!-- w --><a class="postlink" href="http://www.w163.com/*">www.w163.com/*</a><!-- w -->
III.过滤具体到网页子目录,进入若干个/号内
例:http://imguv.21cn.com/images/*;    http://union.homeway.com.cn/images/*
之所以能这样,一般是因为一眼看过去就知道这样的目录下没有好东西,或者看到很多条过滤器中
都出现如下的结构(也表明了网页作者的风格类似),如这里的images
IV.过滤具体到文件,一般就是*.gif,*.swf,*.js类的文件了
例:http://images.chinabyte.com/*.swf; http://www.5ud.com/images/*.gif

综上,只要把问题分开考虑即可:

**************************************************************************************
1.一段体
创建一个如下的表达式(注:本文的正则表达式如果不带前后的两个/号,加入adblock时需加上)
(\.|\/)(您的输入)(\.|\/|_)    (感谢zlowly给出这个filter模型)
前后两个括号中表示的是在你的字段前出现"."或"/",字段后出现".","/"或"_"时候考虑你的字段,
没有这两个限制的话过滤范围就过宽了,例:只写(ad)的话,任何带有ad二字的url均会被过滤。
例:
/(\.|\/)(tomnews|dns99|ad|banner|3721|taobao|unionsky)(s)?(\d)*(\.|\/|_)/
--其中的(s)?是表示s出现0次或1次,则该filter通配ad或者ads,banner或banners,但由于
可以出现0次,所以其他成分仍然可以往中间的括号里加入,即便没有unionskys,taobaos。
--后面的(\d)*表示0-9之间的数字,*号表示0次或多次。
正如zlowly所说,为的是对抗网站根据日期显示不同广告,例如
.../ad20041020/...
然后无非是在中间那个括号中,用|号分开你所有想要匹配的字段了。
知道了这一点,后面的情况就势如破竹了。

2.二段体
创建一个这样的表达式雏形:
\.()\.()
由于已经具体到网址的主体部分,所以前后的/或者.也就不需再出现了
例:
\.(boyis|allyes|cjt1|w163|ppzxw|1000downloads)\.(net|com)
它等价于
http://*.allyes.com/*
*.boyis.com*
*.cjt1.net*
*.w163.com*
*.ppzxw.com*
*.1000downloads.com*
这样看来,应该比较清晰了吧?

3.三段体
例:
(union|adimg|unstat|ulinkjs)\.(baidu|tom|163|sogou)\.(com)
等价于
*adimg.163.com*
*unstat.baidu.com*
*ulinkjs.tom.com*
*union.sogou.com*


    或许有朋友问,为什么分开三种情况呢?整合到一起去有没有可能?
一个很自然的想法是用一个"?"号来表示三段体中的第一段或者出现,或者不出现,
例如想要整合admig.163.com和*.boyis.com,这样写的话:
(adimg)?\.(163|boyis)\.(com)
因为adimg这个字段可出现也可不出现,所以实际上www.163.com这样的地址自然也会被匹配上了,这可不是我们的初衷,
这也就是为什么我觉得应该把各种情况分开考虑,当然更期待高手能解决这个
问题。
    其次,鉴于"|"符号会导致自由组合,整合度不应太高。三段体例子中,第一个括号中最好不要放进通用性太强的字段,
如www,否则"|"符号产生自由组合,若要过滤www.ads8.com和adimage.163.com,自由组合的结果当然www.163.com也被过滤了……
有鉴于此,锁定某一段应该是一个不错的选择,我看第三段应该锁定,也就是说里面没有“或”符号
例如:结尾为com的全部单独写一条,而不要结尾(com|net|org|biz|gov)全加上,
或许会有意想不到的组合的(大家看看whitehouse.com/net/gov就知道了:))

4.具体到文件的,swf/gif类(如有FlashBlock这个扩展的,可以不需要重复过滤swf)
下面是一条很个人的filter,原则也就是在()\.()\.()\/的基本型后面加上了一个.*\.(gif|swf)的文件类型判断,
鉴于这个时候网站网址变化很大,这个filter的整合度就不高了,很多都是直接贴进去然后用"|"符号分开而已。
(www\.(mydrivers|btbbt|shd|5ud)\.com(\.cn)?|search(\d)?\.btchina\.net|image\.cgame\.cn|
onlinedown\.net|218\.106\.83\.10|down\.20cl\.com)\/(image(s)?|photo)?\/.*\.(gif|swf)

等价于:
http://*.onlinedown.net/*.swf
http://*.onlinedown.net/images/*.gif
http://down.20cl.com/*.gif
http://image.cgame.cn/photo/*.gif
http://search3.btchina.net/images/*.gif
http://www.btbbt.com/*.gif
http://www.shd.com.cn/*.gif
http://www.mydrivers.com/images/*.gif
http://www.mydrivers.com/images/*.swf
http://218.106.83.10/images/*.gif
*****************************************************************************************************************

希望拙作能给大家体会正则表达式的强大、学习使用正则表达式带来帮助。
在此最有必要感谢的是AdBlock的(作者(们)?)(0次或1次……呵呵),我在AdBlock的设置中也没找到他(们)?的名字,
网站上也没找到,对这样默默无闻的人表示敬佩。
顺带谢谢提供广告帮助测试AdBlock的所有广告提供商……
附件名称/大小 下载次数 最后更新
正则表达式基础教程.rar (223KB)  3337 2005-07-09 09:46
Waterfox Current和Firefox Nightly都用,逐渐走出XUL扩展依赖
a__gu
小狐狸
小狐狸
  • UID26344
  • 注册日期2008-09-20
  • 最后登录2008-09-21
  • 发帖数2
  • 经验10枚
  • 威望0点
  • 贡献值0点
  • 好评度0点
1楼#
发布于:2004-11-30 00:19
我也来学习了!!
abc@home
千年狐狸
千年狐狸
  • UID6047
  • 注册日期2005-05-16
  • 最后登录2011-01-01
  • 发帖数1681
  • 经验10枚
  • 威望0点
  • 贡献值0点
  • 好评度1点
2楼#
发布于:2004-11-30 00:19
zeroieme
貌似很正确的
ad\d+\.(gif|jpg)
岂不是产生无数个匹配条件,永远算不完
   
回到原帖

当然不是,需要匹配的字串长度不可能无限,url 最长也不超过 1k 吧。

另外视乎你原来要匹配的是甚么,假设你只要匹配 ad0.gif, ad1.gif,...ad9.gif
你认为那个较有效率,较准确?
ad\d\.gif 还是 ad\d{1,10}\.gif 還是 ad\d{1,10}\.(gif|jpg)  還是 ad\d+\.(gif|jpg)



WINXP SP2 MAXTHON (UNICODE) PROXOMITRON
zeroieme
千年狐狸
千年狐狸
  • UID12805
  • 注册日期2006-05-17
  • 最后登录2015-10-11
  • 发帖数1407
  • 经验34枚
  • 威望0点
  • 贡献值20点
  • 好评度0点
  • 社区居民
3楼#
发布于:2004-11-30 00:19

像顶楼例子:

这里本来只有 4 个匹配条件:
adimg.163.com
unstat.baidu.com
ulinkjs.tom.com
union.sogou.com

有效的写法为 (adimg.163|unstat.baidu|ulinkjs.tom|union.sogou)\.com
红色部份更加可省略,减低处理量。

但用上面写法 (union|adimg|unstat|ulinkjs)\.(baidu|tom|163|sogou)\.(com) 便产生 16 个匹配条件:
union.baidu.com
adimg.baidu.com
unstat.baidu.com
ulinkjs.baidu.com
union.tom.com
adimg.tom.com
unstat.tom.com
ulinkjs.tom.com
union.163.com
adimg.163.com
unstat.163.com
ulinkjs.163.com
union.sogou.com
adimg.sogou.com
unstat.sogou.com
ulinkjs.sogou.com

不用说效率及准确度都差得多了。

貌似很正确的
ad\d+\.(gif|jpg)
岂不是产生无数个匹配条件,永远算不完
   
abc@home
千年狐狸
千年狐狸
  • UID6047
  • 注册日期2005-05-16
  • 最后登录2011-01-01
  • 发帖数1681
  • 经验10枚
  • 威望0点
  • 贡献值0点
  • 好评度1点
4楼#
发布于:2004-11-30 00:19
应该是 vb 和 dephi,打错字。 -__-!!



WINXP SP2 MAXTHON (UNICODE) PROXOMITRON
drsu
狐狸大王
狐狸大王
  • UID1387
  • 注册日期2004-12-25
  • 最后登录2008-12-20
  • 发帖数367
  • 经验10枚
  • 威望0点
  • 贡献值0点
  • 好评度0点
5楼#
发布于:2004-11-30 00:19
abc@home
另外大家都知道 adblock 是用 javascript 编写的,而 javascript 是 interpret 语言,速度一般只有  c++,vs,dephani 等 compiled language/machine code 的 10 到 20 分之一,
回到原帖


你总算逻辑正常了。
不过,
"vs","dephani"是什么语言?
abc@home
千年狐狸
千年狐狸
  • UID6047
  • 注册日期2005-05-16
  • 最后登录2011-01-01
  • 发帖数1681
  • 经验10枚
  • 威望0点
  • 贡献值0点
  • 好评度1点
6楼#
发布于:2004-11-30 00:19
最近正则在 maxthon 论坛很火,有人转了这个帖子。看了看,感觉大家对正则或过滤似乎还是不太掌握,在 maxthon 论坛提了些意见,顺便在这里分享一下。

首先过滤速度主要视乎过滤规则的复杂性,或匹配条件的多少,而非过滤规则多少。所以不要把匹配条件都免勉强跻进同一规则。一条效率低的规则可以比十条规则慢。

像顶楼例子:
3.三段体
例:
(union|adimg|unstat|ulinkjs)\.(baidu|tom|163|sogou)\.(com)
等价于
*adimg.163.com*
*unstat.baidu.com*
*ulinkjs.tom.com*
*union.sogou.com*

这里本来只有 4 个匹配条件:
adimg.163.com
unstat.baidu.com
ulinkjs.tom.com
union.sogou.com

有效的写法为 (adimg.163|unstat.baidu|ulinkjs.tom|union.sogou)\.com
红色部份更加可省略,减低处理量。

但用上面写法 (union|adimg|unstat|ulinkjs)\.(baidu|tom|163|sogou)\.(com) 便产生 16 个匹配条件:
union.baidu.com
adimg.baidu.com
unstat.baidu.com
ulinkjs.baidu.com
union.tom.com
adimg.tom.com
unstat.tom.com
ulinkjs.tom.com
union.163.com
adimg.163.com
unstat.163.com
ulinkjs.163.com
union.sogou.com
adimg.sogou.com
unstat.sogou.com
ulinkjs.sogou.com

不用说效率及准确度都差得多了。

另外大家都知道 adblock 是用 javascript 编写的,而 javascript 是 interpret 语言,速度一般只有  c++,vs,dephani 等 compiled language/machine code 的 10 到 20 分之一,不适宜作大量运算,否则会做成像某版主说的用 css 下载隐藏感觉上比用 adblock 直接过滤还更快。



WINXP SP2 MAXTHON (UNICODE) PROXOMITRON
ancintosh
狐狸大王
狐狸大王
  • UID11069
  • 注册日期2006-01-11
  • 最后登录2011-08-14
  • 发帖数423
  • 经验10枚
  • 威望0点
  • 贡献值0点
  • 好评度0点
7楼#
发布于:2004-11-30 00:19
问一下.正则表达式里通配符是什么?好象不是*吧.还有[]括号是什么含义?
nonname
小狐狸
小狐狸
  • UID2855
  • 注册日期2005-02-07
  • 最后登录2013-02-25
  • 发帖数51
  • 经验10枚
  • 威望0点
  • 贡献值0点
  • 好评度0点
8楼#
发布于:2004-11-30 00:19
Freewebs Page Not Found

We are sorry, this page was not found. Please check the URL and try again.


.......
Fantasy
火狐狸
火狐狸
  • UID10416
  • 注册日期2005-12-07
  • 最后登录2016-01-06
  • 发帖数171
  • 经验77枚
  • 威望0点
  • 贡献值30点
  • 好评度3点
  • 社区居民
  • 忠实会员
9楼#
发布于:2004-11-30 00:19
谢谢楼主  才发现原来ADblock功能这么强大 试了一下 很爽 看到不爽的就可以cancel掉
兰烟
小狐狸
小狐狸
  • UID4273
  • 注册日期2005-03-22
  • 最后登录2006-01-01
  • 发帖数40
  • 经验10枚
  • 威望0点
  • 贡献值0点
  • 好评度0点
10楼#
发布于:2004-11-30 00:19
很多的链接无效了。
流羽
小狐狸
小狐狸
  • UID4608
  • 注册日期2005-03-31
  • 最后登录2005-10-21
  • 发帖数13
  • 经验10枚
  • 威望0点
  • 贡献值0点
  • 好评度0点
11楼#
发布于:2004-11-30 00:19
汗,附件裏怎么是亂碼啊!!!!!!!!!!
CrossBud
黄金狐狸
黄金狐狸
  • UID7038
  • 注册日期2005-06-29
  • 最后登录2016-08-31
  • 发帖数5948
  • 经验12枚
  • 威望2点
  • 贡献值40点
  • 好评度20点
  • 社区居民
12楼#
发布于:2004-11-30 00:19
.crsky.com/Ggao/*.gif
.crsky.com/Ggao/*.jpg
.crsky.com/Ggao/*.swf
这三个合在一起用正则表达式如何写?
自己瞎写的/Ggao\.(swf|gif|jpg)/*不行~~
黑色森林
火狐狸
火狐狸
  • UID7511
  • 注册日期2005-07-22
  • 最后登录2014-05-15
  • 发帖数202
  • 经验10枚
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 社区居民
13楼#
发布于:2004-11-30 00:19
虽然不是很懂,但总算学了点,相当不错,

经常浏览的网站的SWF和GIF都统统消失啦!

正则万岁!

ADBLOCK万岁!

FF万岁!

自由万岁!

IE跟毛毛虫睡!
你家阿姨又崩溃了!!
landina
小狐狸
小狐狸
  • UID8229
  • 注册日期2005-08-26
  • 最后登录2005-08-26
  • 发帖数1
  • 经验10枚
  • 威望0点
  • 贡献值0点
  • 好评度0点
14楼#
发布于:2004-11-30 00:19
我如何写这样的表达式来提取数据?
<META name="description" content="浙江省最大的综合性网站,宁波的门户站点。内容涵盖游戏、证券、电脑、旅游、企业、书楼、贺卡、人才、娱乐、时尚、汽车、直播、导航、论坛、聊天、美术、手机、体育、数码、音乐、生活、硬件、软件、网吧、影库、房产、影院等等。">
<meta name="keywords" content="游戏;证券;电脑;旅游;企业;书楼;贺卡;人才;娱乐;时尚;汽车;直播;导航;论坛;聊天;美术;手机;体育;数码;音乐;生活;硬件;软件;网吧;影库;房产;影院">

我想提取上面部分的Content的值
同时我想提取下面部分的charset的值,如何用正则表达式表述?

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
上一页
游客

返回顶部