Swift
meta
swift3

ライブラリを使わないでmetaタグを取得する

久々の投稿だ〜(✿´ ꒳ ` )
ここではWKWebViewからhtmlを取得し、そのhtmlからmetaタグ達を取得する方法を書きます!!urlから行いたい方はいったんhtmlまで取得を行なってください🙇‍♀️

ちなみに、ライブラリ使うなら以下おすすめ。取れるものがこれで揃えば以下のライブラリは使いやすいのでおすすめします!!

https://github.com/satoshi-takano/OpenGraph

追記:
コメントをいただきました。
metaタグの[<meta property=]の間の余白がまちまちでくる可能性がある場合は以下の正規表現の\sは\s+としてください。
まちまちで来る可能性ですがmetaタグ取得のサイトが決まっていないなどの場合です。

code

WKWebViewからhtmlをゲットして処理しているところ

self.wkWebView?.evaluateJavaScript("document.getElementsByTagName('html')[0].innerHTML", completionHandler: { (html, error) -> Void in
            if let html = html{
                let metas = htmlPaser.parse(htmlString: html as! String)
                let parseMetas = htmlPaser.parseMetasGet(htmlString: html as! NSString, textCheckingResults:metas)
                print("\(parseMetas)")
            }

            if let error = error{
                let errorText = error.localizedDescription
                print("\(errorText)")
            }
        })

大元のクラス

class htmlPaser: NSObject {

    static func parse(htmlString: String) -> [NSTextCheckingResult]{
        let metatagRegex  = try! NSRegularExpression(
            pattern: "<meta\\sproperty=(?:\"|\')(og|article):([a-zA_Z:]+?)(?:\"|\')\\scontent=\"(.*?)\"",
            options: [.dotMatchesLineSeparators]
        )
        let metaTagMatches = metatagRegex.matches(in: htmlString,
                                                  options: [],
                                                  range: NSMakeRange(0, htmlString.count))
        if metaTagMatches.isEmpty {
            return []
        }else{
            return metaTagMatches
        }
    }

    static func parseMetasGet(htmlString: NSString, textCheckingResults:[NSTextCheckingResult]) -> [String:String]{
        var parseMetas:[String:String] = [:]
        textCheckingResults.forEach {
            let withRange:NSString = htmlString.substring(with: NSRange(location: $0.range.location, length: ($0.range.length))) as NSString
            let regularExpression:String = "^<meta\\sproperty=(?:\"|\')(og|article):([a-zA_Z:]+?)(?:\"|\')\\scontent=\"(.*?)\""
            let rd = try? NSRegularExpression(pattern: regularExpression, options: NSRegularExpression.Options())

            if let r = rd?.firstMatch(in: withRange as String, options: NSRegularExpression.MatchingOptions(), range: NSMakeRange(0, withRange.length)) {
                let property0:String = withRange.substring(with: r.rangeAt(1))
                let property1:String = withRange.substring(with: r.rangeAt(2))
                let content:String = withRange.substring(with: r.rangeAt(3))

                let property = property0 + ":" + property1
                parseMetas[property] = content
            }else{
                print("値はありません")
            }
        }
        return parseMetas
    }
}

やっていることを大まかに説明

  • jsを使いhtmlを取得
  • そのhtmlからmetaタグを抜き出す(語弊があります。詳しくはmetaタグのある位置情報などを格納する集合体みたいなの作っています)
  • 最後metaタグの文字列を出して行ってそれをいい感じに分解、辞書に格納しています

参考にさせていただいたurl

https://github.com/satoshi-takano/OpenGraph
https://qiita.com/_tid_/items/8705275813e740d693ef
https://qiita.com/moaible/items/85d80173bb8ed7f64b74
http://www.office-matsunaga.biz/ios/description.php?id=28
https://qiita.com/niwasawa/items/6237989e60a3a0155ff2

最後に

ネーミンぐセンスや、これはこうした方がもっと素敵になるよの意見を期待しています(>ω<)
宜しくお願いします。正規表現( ・ὢ・ 。)またsample作れればやりたいと思います!