読者です 読者をやめる 読者になる 読者になる

iOS7でHTMLを取得してパースする

作業環境

準備

1. Objective-C-HMTL-Parserの導入

HTMLをパースするために「Objective-C-HMTL-Parser」というライブラリを使います。ソースコードGitHubで公開されていますので、上記のリンクから適当にローカルにクローンしてください。クローンしたもののうち、README.md以外をXcodeの自分のプロジェクトにコピーしてください。コピーする際に、「Copy items to destination's group folder」にチェックを必ず付けてください。

2. 依存ライブラリの追加

Objective-C-HMTL-Parserはlibxml2.dylibのラッパーですので、libxml2.dylibを追加しないと動きません。

General -> Linked Frameworks and Librariesでlibxml2.dylibを追加してください。

3. インクルードパスの追加

Objective-C-HMTL-Parserとlibxml2.dylibを追加していざ実行しようとするとビルドが失敗します。libxml/HTMLtree.hとlibxml/HTMLparser.hが見つからないようですので、libxmlをインクルードパスとして追加しないといけません。

Build Settings -> All -> Search Paths -> Header Search Paths -> Debugで$(SDKROOT)/usr/include/libxml2を追加してください。

Header Search Pathsは少々見つけにくい所にあります。Build Settingsを選択した後に、Allタブを選択しないとHeader Search Pathsが出てこないと思います。どうしても見つからない場合はこちら

HTMLの取得

以下は指定したページのHTMLを取ってくる部分のソースコードです。

NSURL *url = [NSURL URLWithString:@"URL"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

if (!connection) {
    NSLog(@"Connection error");
}

NSURLConnectionをallocした時点で同期的にWebページにアクセスします。

データを受け取る

Delegateを用いてデータを受け取る部分のソースコードです。

データを受け取るクラスのヘッダでNSURLConnectionDataDelegateをプロトコルとして追加してください。

- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    receivedData = [[NSMutableData alloc] init];
}

- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [receivedData appendData:data];
}

- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
    NSString *html = [[NSString alloc] initWithBytes:receivedData.bytes length:receivedData.length encoding:NSShiftJISStringEncoding];
}

上記のソースコードでは、たまたまShift-JISなページを取得していたのですが、取得対象がUTF-8なページであれば、encodingをNSUTF8StringEncodingに変更してください。そして、connectionDidFinishLoadingメソッド内でNSStringに変換した後は煮るなり焼くなり好きにしましょう。

HTMLをパースする

Objective-C-HMTL-Parserを使って取得したHTMLをパースします。

NSError *error = nil;
HTMLParser *parser = [[HTMLParser alloc] initWithString:html error:&error];
HTMLNode *bodyNode = [parser body];
NSArray *aNodes = [bodyNode findChildTags:@"a"];
for (HTMLNode *node in aNodes) {
    NSLog(@"%@", [node getAttributeNamed:@"href"]);
}

上記のコードでは、HTMLのBodyに含まれるaタグを全て取得して、hrefをNSLogで吐き出しています。

参考サイト