奇技淫巧 - 阅读主题
<<  <  1  >  >>

决战RSS的垃圾代码

好(0) 差(0) 阅读(541) 评论(0)
Wen 给 Wen 发消息 给 Wen 发email
poster face
等级:◆◆◆◆◇◇


前几天装了个lilina用来聚合(订阅)好友的Blog。很快发现这些聚合来的RSS其中的HTML代码很不规范,把声明为XHTML 1.0 Strict的页面破坏得不成样子。由于开头只是聚合了源自BlogCN的RSS,看看垃圾代码不算多,主要有<br />的不规范用法<br>和摘要对全文截断时会截断HTML标签,出现诸如“<b”(<br>被截断)、“&nbs”(&nbsp;被截断)的东西;于是就写了段小程序三下五除二把垃圾代码摆平了。

谁知过了两天订了个源自MSN Space的RSS,发现垃圾代码超级多,img标签没有用“/>”结尾;用了一堆font标签、一堆border属性;height、width属性值画蛇添足加了个“px”;有很多空的span标签和div标签;有些属性值没有用引号引起来;url中的“&”没有用实体“&amp;”代替。这么多垃圾可够麻烦的,起初让lilina把HTML标签都过滤掉(把“<”替换成“&lt;”,“>”替换成“&gt;”),结果页面非常难看。后来又想单独把lilina这页的文档类型DOCTYPE声明为HTML 4.01 Transitional,但是一想就算“&”在HTML 4.01中都是非法的,而且小区用的是模版,要改DOCTYPE可不是容易的事情。干脆一不做二不休,专门写一个函数用来清理垃圾代码,堪称一微型Tidy了(我当然知道PHP有Tidy的Extension啊,可是虚拟主机不会把这种东西编译进来啊)。下面就把我的微型Tidy贴一下:

function clean_summary($strSummary) {
    // 把结尾错误截断的HTML标签去掉
    $arrMatchings = array(
        array("<", ">"),
        array("&", ";")
    );
    foreach ($arrMatchings as $arrMatching) {
        $intL = strrpos($strSummary, $arrMatching[0]);
        if ($intL !== false) {
            $intR = strrpos($strSummary, $arrMatching[1]);
            if ($intL > $intR) $strSummary = substr($strSummary, 0, $intL);
        }
    }
    // 为了效率,能用str_replace搞定的就不用正则表达式
    $strSummary = str_replace(array(
        "<br>", "<br/>", "</font>", "</span>"
    ), array(
        "<br />", "<br />", "", ""
    ), $strSummary);
    // 有些非得用正则表达式,顺便复习一下正则表达式的用法
    $arrPatterns = array(
        "#<script[.\s]*</script>#is",
        "#<script.*/>#is",
        "#<iframe[.\s]*</iframe>#is",
        "#<iframe.*/>#is",
        "#<img([^>]*)([^/])>#is",
        '#(height|width)="?(\d+)(px)?"?#is',
        "#border=[^\s]* #is",
        "#<font[^>]*>#is",
        "#<span[^>]*>#is",
        "#<div[^>]*></div>#is",
        "#<p[^>]*></p>#is"
    );
    $arrReplacements = array(
        "", "", "", "",
        "<img\1\2 />",
        '\1="\2"',
        "", "", "", "", ""
    );
    $strSummary = preg_replace($arrPatterns, $arrReplacements, $strSummary);
    // 找出单独的“&”替换成“&amp;”
    $intAnd = -1;
    while (($intAnd = strpos($strSummary, "&", $intAnd + 1)) !== false) {
        if (($intSemicolon = strpos($strSummary, ";", $intAnd)) !== false) {
            if ($intSemicolon - $intAnd > 6) {
                $strSummary = substr_replace($strSummary, "&amp;", $intAnd, 1);
                continue;
            }
            $strEntity = substr($strSummary, $intAnd, $intSemicolon - $intAnd + 1);
            $arrEntities = array(
                "&nbsp;", "&amp;", "&lt;", "&gt;", "&quot;"
            );
            $boolNotEscaped = true;
            foreach ($arrEntities as $e) {
                if ($strEntity == $e) {
                    $boolNotEscaped = false;
                    break;
                }
            }
            if (!$boolNotEscaped) continue;
            if (!preg_match("^&#\d+;\$", $strEntity)) {
                $strSummary = substr_replace($strSummary, "&amp;", $intAnd, 1);
            }
        } else $strSummary = substr_replace($strSummary, "&amp;", $intAnd, 1);
    }
    return $strSummary;
}
Share/Save/Bookmark
最后修改:Wen 于 2005-08-20 10:45:48

发表于 2005-08-18 10:51:08
奇技淫巧 - 阅读主题
<<  <  1  >  >>
发表评论
评论将以 过客 的名义发表
你的名字/昵称:
为减少垃圾评论,请准确回答问题:

注意:不超过 65535 字节,不支持HTML,支持NN Code

| | | 注册 | 忘记密码
分类浏览: 足迹 | 美食 | 开心 | 奇技淫巧 | 科学 | 音视 | 琐事 | WENSH事务 | 过客留言 | 前梦想国度 |
English categories: Footprints | Recipes | Fun | Tech | Science | Entertainment | Life | WENSH Affairs | Guests' Msgs |
| 链接 | 服务 | 留言 | 关于 NetNest |
Valid XHTML 1.0 | Valid CSS2 | WAI-A WCAG 1.0
LinkReferral | Multiply the traffic to your website... FREE
W3Csites.com Listed | Travel blogs | Travel | Top Blogs | blogarama.com
Directory of Travel Blogs | Travel Blogs - Blog Top Sites | Web Hosting Directory by Blog Flux | | Blog Ratings
Copyright 2005-2008 WEN'S Horizon [32/0.058]
Powered by NetNest 2.1.0.081019 © 2004-2008 NetNest Group