Hatena::ブログ(Diary)

cooldaemonの備忘録 RSSフィード

2009-09-12

SimpleHttpClient に HTML のフィルタを追加しました(HTML Document に対して XPath が使えます)

SimpleHttpClientKissXML+HTML を組み込んで HTML フィルタを作成しました。

下記のように、SimpleHttpClient のオブジェクトを作成し・・・

SimpleHttpClient *client = [[SimpleHttpClient alloc] initWithDelegate:self];

HTML 用のフィルタを設定し・・・

[client
    setFilter:SimpleHttpClientFilterHTML
      forHost:@"d.hatena.ne.jp"
];

リクエストを送ると・・・

[client
           get:@"http://d.hatena.ne.jp/cooldaemon/20090911/1252637257"
    parameters:nil
       context:nil
];

DDXMLDocument のオブジェクトが受け取れます。

- (void)simpleHttpClientOperationDidFinishLoading:(SimpleHttpClientOperation *)operation
                                     filteredData:(id)data
{
    [_html release];
    _html = (DDXMLDocument *)[data retain];
}

XPath を使うには、下記のようにします。

NSError *error = nil;
NSArray *body = [_html
    nodesForXPath:@"id(\"days\")//div[@class=\"body\"]//h3/following-sibling::*|id(\"days\")//div[@class=\"body\" and not(.//h3)]"
            error:&error
];

NSLog("%@", [body componentsJoinedByString:@""]);

詳しくは、test/TestHatenaDiaryHTML.m をご参照下さい。

2009-09-11

KissXML で HTML を扱えるように、KissXML+HTML を作りました

この話ですが、よくよく考えたら Objective-C にはカテゴリがあるので、Patch を作る必要はありませんでした。

Source Code と使い方は、こちら

HTML 対応とは全く無関係ですが、こっそり、xmlParseMemory を xmlReadMemory に入れ替えてます。

ついでに、使われていなかった option を利用して htmlReadMemory と xmlReadMemory のオプションを指定できるようにしました。

KissXML がバージョンアップすると利用できなくなる可能性もありますが、きっとすぐに対応できるハズ。

KissXML の開発チームに連絡してみよっと。

2009-09-10

KissXML で HTML を無理矢理使う方法

KissXML で HTML を扱えるように、KissXML+HTML を作りました

そんなに KissXML に思い入れがあるわけではないのですが、HTML でも XPath を使いたいのと、XPathQuery と KissXML を一つのアプリで併用するのも嫌だったので、少しだけ KissXML の Source を追って HTML を使えるよう修正してみました。

ちなみに、この修正を行なうと XML が扱えなくなります。SimpleHttpClient の HTML フィルタを作成する際には、両方扱えるような修正を入れようかと思っています。その後に patch を作成する予定です。(patch を開発元に送るか検討中)

DDXMLDocument.h の頭で HTMLparser.h を import します。

#import <libxml/HTMLparser.h>

DDXMLDocument.m

- (id)initWithData:(NSData *)data options:(unsigned int)mask error:(NSError **)error
{
    //..snip..
    xmlDocPtr doc = xmlParseMemory([data bytes], [data length]);
    //..snip..
}

xmlParseMemory ではなく、htmlReadMemory を使用するように修正します。

xmlDocPtr doc = htmlReadMemory([data bytes], [data length], "", NULL, HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR);

DDXMLNode.m

+ (BOOL)isXmlDocPtr:(xmlKindPtr)kindPtr
{
    return kindPtr->type == XML_DOCUMENT_NODE;
}

type が XML_HTML_DOCUMENT_NODE の時も真を返すようにします。

    return kindPtr->type == XML_DOCUMENT_NODE
        || kindPtr->type == XML_HTML_DOCUMENT_NODE;

たったこれだけで、KissXML が HTML を扱えるようになります。

ちなみに手元では、wedata にある LDRFullFeed を使って本文を抽出する事ができました。