@shu223 さんのpost ”手軽に使えるSwift製HTMLパーサ「Ji」” に名前が出ていたので
Kannaも紹介記事を書いてみます。
Github: Kanna(鉋)
追記:2015/9/2
1. バージョンアップしました(0.1.3 => 0.1.4)
手元のバージョンで説明を書いてしまっていたため一部コードが動かない状態でした・・・。
2. マニュアルセットアップに方法2を追記しました。
手動でframeworkをビルドする方法です。
マニュアルセットアップするならコチラの方が楽です。
Kannaとは?
Swift製のHTML/XMLパーサです。
他パーサとの違いは CSSセレクタでも要素抽出 ができるぐらいです。
元々はSwift-HTML-Parserという名前でした。
"SwiftでObjCコードを書き換えてみる(Objective-C-HTML-Parser)"
最近RubyのNokogiriを知って、似せる形で書き換えたのでついでに名前も変えました。
導入手順
※Swift2の場合はREADME.mdを参照してください。
CocoaPods
use_frameworks!
pod 'Kanna'
$ pod install
Carthage
github "tid-kijyun/Kanna" >= 0.1.0
$ carthage update
マニュアルセットアップ(方法1)
- プロジェクトを選択して"Linked Frameworks and Libraries" に
libxml2.dylib
を追加 - ”Header Search Paths" に
$(SDKROOT)/usr/include/libxml2
を追加 - Bridging Headerに下記を追加
#import <libxml/HTMLtree.h>
#import <libxml/xpathInternals.h>
Bridging Headerが無い場合は作成してください。
4. Souceフォルダ配下の下記ファイルをプロジェクトに追加
Kanna.swift
CSS.swift
libxml/libxmlHTMLDocument.swift
libxml/libxmlHTMLNode.swift
libxml/libxmlParserOption.swift
マニュアルセットアップ(方法2)
出力される場所を見つけられるなら手動でframeworkをビルドする方法もあります。
-
Kanna.xcworkspace
をXcodeで開いてビルド - 生成された
Release-iphoneos
ディレクトリ内のKanna.framework
をプロジェクトに登録
参考:Github Issue #28 Use in Projects
使い方
インポート
// マニュアルセットアップの場合は不要です。
import Kanna
Kannaオブジェクトを作成
HTMLは別途引っ張ってくる必要があります。(だいたいAlamofire使うので入れていません・・・)
let url = NSURL(string: "https://en.wikipedia.org/wiki/cat")
let data = NSData(contentsOfURL: url!)
let doc = HTML(html: data!, encoding: NSUTF8StringEncoding)
文字列から作成することもできます。
let html = "<html>...</html>"
let doc = HTML(html: html, encoding: NSUTF8StringEncoding)
CSSセレクタで特定の要素を抽出する
// aタグ と linkタグ を抽出
nodes = doc?.css("a, link")
実際使うとこんな感じです。
// HTML内のリンク(URL)を抜き出す
for node in doc!.css("a, link") {
println(node["href"]) // href属性に設定されている文字列を出力
}
Xpathで特定の要素を抽出する(結果はCSSセレクタの場合と同じ)
// aタグ と linkタグ を抽出
nodes = doc?.xpath("//a | //link")
// HTML内のリンク(URL)を抜き出す
for node in doc!.xpath("//a | //link") {
println(node["href"]) // href属性に設定されている文字列を出力
}
属性値で絞り込む
Wikipediaのコンテンツをスクレイピングする場合・・・
// cssセレクタ ver
let contentDivNode = doc?.body?.css("div#content div#bodyContent div#mw-content-text")
// xpath ver
let contentDivNode = doc?.body?.xpath("div[@id='content']/div[@id='bodyContent']/div[@id='mw-content-text']")
こう書いてもOKです(bodyを省略)
// cssセレクタ ver
let contentDivNode = doc?.css("div#content div#bodyContent div#mw-content-text")
// xpath ver
let contentDivNode = doc?.xpath("//div[@id='content']/div[@id='bodyContent']/div[@id='mw-content-text']")
細かい使い方
タイトルを取得する
doc?.title //=> Optional("hoge title")
headノードを取得する
head:
メソッドで取得できます
let head = doc?.head
// 下記でも同じ
let head = doc?.css("head").first
bodyノードを取得する
body:
メソッドで取得できます
let body = doc?.body
// 下記でも同じ
let body = doc?.css("body").first
タグ名を取得する
tagName
で取得できます。
let node = doc?.css("div").first
node?.tagName //=> Optional("div")
属性値を取得する
["ATTR_NAME"]
で取得できます。
let node = doc?.css("a[href]").first
node?["href"] //=> Optional("http://...")
HTMLを取得する
toHTML
で取得できます。
let node = doc?.css("div").first
node?.toHTML //=> Optional("<div...</div>")
タグの中身を取得する
innerHTML
で取得できます。
let node = doc?.css("div").first
node?.innerHTML //=> Optional("...")
その他
ご質問・ご指摘ありましたらお願いします。
プルリクも大歓迎です!