はじめに
独学でプログラミング学び始めて約1年、業務でプログラムを書き始めて2ヶ月、Swift始めて1ヶ月のSwifterです。
最近RSSリーダーを自作しているのですが、アプリ開発のイロハを学ぶにはちょうど良いものなんじゃないかと思います。なんで良いかはまた別途記事にしようかなと。
今回はRSSからパースした文字列中のimg src = "hogehoge"からhogehogeを抜き取ることをやります。こんな感じ。
これから
<p><img src="hogehoge.png">hogehogeがpiyopiyoでやばい!</p>
これを抜き出す
hogehoge.png
なんでやるのか
RSSをパースして内容を色々取得すると、itemとかdescriptionのタグでimg src="hogehoge"が取得できるものがあります。これを各記事のサムネイル画像として使えないかと思い、試行錯誤しました。
方針①
まずはこちらをご覧ください。私が2週間ほど前に書いたコードです。
summaryには以下のような文字列が入っていると仮定してください。
summary = "<p><img src="hogehoge.png">hogehogeがpiyopiyoでやばい!</p>"
function getImgString(summary:NSString?) -> String?{
if let summary = summary {
let checkStr: NSMutableString = summary.mutableCopy() as! NSMutableString
var range: NSRange = checkStr.rangeOfString("img src=\"" as String) as NSRange
var startSearchLocation = 0
if range.location != NSNotFound {
startSearchLocation = range.location
var searchRange: NSRange = NSRange()
// 9は「img src="」の文字数
searchRange.location = startSearchLocation + 9
for index in startSearchLocation..<summary.length{
searchRange.length = index
range = checkStr.rangeOfString("\"", options: NSStringCompareOptions.RegularExpressionSearch, range: searchRange)
if range.location != NSNotFound {
return checkStr.substringWithRange(NSMakeRange(searchRange.location, index - 1))
}
}
}
}
}
正直これ何やってるか自分でもわからないくらいなんですが、確かこの時はこんな方針でやってました。
1. まず文字列(新たに用意した可変数checkStr)に「img src="」が含まれているか判定
2. 含まれていればそこから次の「"」まで元の文であるsummaryの中を検索
3. 次の「"」が見つかればそこまでの文字列を切り取る
こうすることで、一応目的は達成されていました。
問題
・見辛い
・何やってるか理解ができない
・タグがimg scr=\"http://〜 のようになっていたり、エスケープ文字が使われていたりするとクラッシュする
・保守性が悪い(気がする)
なので方針を変えてみました。
方針②
- 文字列中に「img scr="○○○○"」があるかを正規表現で判定
- 含まれていれば、まずは「img src="○○○"」の形に変換
- そこから「"img src="」を削除
- 最後に残った「"」を削除
こんな感じになりました。
summary = "<p><img src="hogehoge.png">hogehogeがpiyopiyoでやばい!</p>"
function getImgString(summary:NSString?) -> String?{
if let summary = summary {
let checkStr: NSMutableString = summary.mutableCopy() as! NSMutableString
do {
let reguxp: NSRegularExpression = try NSRegularExpression(pattern: "img src=\"(.+?)\"", options: .CaseInsensitive)
let matches = reguxp.matchesInString(checkStr as String, options: [], range: NSMakeRange(0, summary.length))
guard let targetRange = matches.first?.range else {return nil}
var deleteImgSrcStr = checkStr.substringWithRange(targetRange)
guard let imgSrcRange = deleteImgSrcStr.rangeOfString("img src=\"" as String) else {return nil}
deleteImgSrcStr = deleteImgSrcStr.stringByReplacingCharactersInRange(imgSrcRange, withString: "")
let endPoint = deleteImgSrcStr.characters.count - 1
let imgStr = (deleteImgSrcStr as NSString).substringToIndex(endPoint)
return imgStr
} catch {
return nil
}
return nil
}
- patternに当てはまるものがcheckStrにあるかチェック
- 含まれていればそのNSRange targetRangeを取得
- 取得したtargetRangeを使って、長いHTMLタグから「img src="○○○"」という文字列のみに変換
- 「img src="」を削除
- 文字列の最後に残った「"」をendpointとsubstringToIndexメソッドを使って削除
こうすることでhogehoge.pngが取得でき、無事目的達成です。
最後に
正規表現はもっと良いやりかたがあるかと思います。ただ、正規表現いつになっても慣れません。。。
また、3,4を同時にできるといいんですが良いやり方が思い浮かばず。。。 コメントお待ちしてます!