2007/03/17

BloggerのFeedにも「続きを読む」を適用してみる。

無精をしたいが為に何通りかの方法を試してみたりしてきたBloggerでの「続きを読む」機能ですが、現在はtemplate + javascriptな方法で運用中です。

このFeedを読んでいる方には迷惑な話かもしれませんが、もう少し「続きを楽しむ」って事で、Feedにも適用してみました。


RSSなりAtomなFeedをBlog Readerで購読していると、見かけるのが記事全文を表示しないタイプのFeedです。

BloggerでもSummaryなFeedが用意されているのですが、これは先頭からの文字数規定でSummaryとするタイプであり、折角「続きを読む」な書き方をしているのにちょっと理不尽な感じがしまして、別サーバーを介して<div class="fullpost">内を削るFeedを作ってみました。

実際には私はFeedburnerを利用していますので、こちらにもSummary機能はあるのですが、こちらも規定文字数までを出力するタイプなので、FeedburnerのFeed元を自サーバーに変更して対応しました。

サーバーはASP.Netな環境であり、今回のFeedはc#で書かれたaspxページで提供されています。

BloggerのコンテンツはXHTML 1.0 Strictだと思っていたのですが、私個人がそれをやや無視したコンテンツを書いていたり、Picasaから投稿した際に生成されたと思われる画像への<a>タグのAttributeの記述で要素間の空白が無いケース等があり、xmlなパーサー使って読み込んでremoveChildで消せば楽々だとかの思いは適いませんでした。

今更過去に書いたPostの細部を確認しながら修正する気力も湧かないなかったので、XML Parserを使うのではなく正規表現を交えたコードでゴリゴリと<div class="fullpost">を消しこむようにしました。

それほどASP.NetなサーバーをBloggerのFeedの加工なんかに利用できる方もいるとは思えませんが、コードはこんな感じです。

public partial class atom : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        XmlDocument xml = new XmlDocument();
        WebClient webClient = new WebClient();
        String sFeed = (Request["feed"]!=null
                    ?Request["feed"]
                    :@"http://isawseashell.blogspot.com/feeds/posts/default" );
             
        Stream webDataStream = webClient.OpenRead(sFeed);

        xml.Load(webDataStream);

        XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable);
        nsmgr.AddNamespace("atom""http://www.w3.org/2005/Atom");


        XmlNodeList contents = xml.SelectNodes("//atom:entry//atom:content", nsmgr);

        foreach (XmlNode content in contents)
        {
            string sContent = content.InnerText;

            sContent = removeFullpost(sContent);

            content.InnerText = sContent
                + "<br/>【記事全文はBlogサイト I saw seasheels. にて!!】";

        } // __forEach

        Response.Write(xml.OuterXml);

    }

    //
    private string removeFullpost(string sContent)
    {

        Regex rexp = new Regex("<div.*class=.*fullpost.*>");

        int nStartPos = rexp.Match(sContent).Index;

        if (nStartPos > 0)
        {
            int nEndPos = findEndTag(sContent, nStartPos, "div");

            sContent = sContent.Substring(0, nStartPos)
                    + (nEndPos + "</div>".Length + 2 <= sContent.Length
                        ? sContent.Substring(nEndPos + "</div>".Length + 2)
                        : "");
        }

        return sContent;
    }

    private int findEndTag(string s, int nStartPos, string sTagName)
    {
        Regex rexpEnd = new Regex("</" + sTagName + ".*>");
        Regex rexpStart = new Regex("<" + sTagName + ".*>");

        int nEndPos = rexpEnd.Match(s, nStartPos + 1).Index;
        int nInnerStart = rexpStart.Match(s, nStartPos + 1).Index;
        if (nInnerStart > 0 && nInnerStart < nEndPos)
        {
            nStartPos = findEndTag(s, nInnerStart, sTagName);

            nEndPos = findEndTag(s, nStartPos, sTagName);
        }
        else
        {
            nEndPos = rexpEnd.Match(s, nStartPos + 1).Index;
        }

        return nEndPos;
    }

}


省略時の文言もパラメータにしようとかは思っていますが、現在はこんな感じて書いてあります。そしてこれをホスティングしているサーバーのURLをFeedBurnerのFeed元に指定しいます。

今現在このBlogのFeedを見ると記事が省略されいるかと思います。

このコードをHostingしているサーバーの規約・制約があるのでサービスとして公開する事は出来ませんが、Adsense等の広告収入がServerのレンタル代(月1000円程度)をカバー出来るようになったらなぁ・・とかと夢を見ています(笑

こんな感じで実はちょっと迷惑は機能を実装したりして、自己満足に浸っていられるのがPrivateなBlogの良さではないかと。

関連のありそうな記事

1 コメント:

Kuribo さんのコメント...

FeedBurner のフィードを取り込んでリーダーで見てみました。コードはよく分からないんですが(汗)、すごいですね!