import Foundation
func extractSpanText(from html: String) -> [String] {
var results: [String] = []
let pattern = "<span>(.*?)</span>"
let regex = try! NSRegularExpression(pattern: pattern, options: [.dotMatchesLineSeparators])
let range = NSRange(location: 0, length: html.utf16.count)
regex.enumerateMatches(in: html, options: [], range: range) { match, _, _ in
if let match = match, match.numberOfRanges > 1 {
let spanRange = match.range(at: 1)
if let spanText = (html as NSString).substring(with: spanRange) as String? {
results.append(spanText)
}
}
}
return results
}
// 示例使用
let longHtmlText = "<div><span>content1</span><span>content2</span></div>"
let spanTexts = extractSpanText(from: longHtmlText)
print(spanTexts)
正则表达式设计思路
<span>
和 </span>
界定:使用 <span>
和 </span>
来明确需要匹配的标签起始和结束位置。
- 非贪婪匹配:使用
.*?
来表示匹配尽可能少的字符,直到遇到第一个 </span>
,这样可以处理多层嵌套标签,避免误匹配。例如在 <span><span>inner</span>outer</span>
这种嵌套结构中,能正确提取出内层和外层 <span>
标签内的文本。
dotMatchesLineSeparators
选项:在初始化 NSRegularExpression
时使用 .dotMatchesLineSeparators
选项,这样 .
可以匹配换行符,从而处理跨多行的 <span>
标签内容。
优化匹配效率以应对长文本
- 非贪婪匹配:如上述,使用
.*?
非贪婪模式,减少不必要的回溯,提高匹配速度。
- 预编译正则表达式:将正则表达式预编译成
NSRegularExpression
对象,而不是每次都动态编译,提高多次匹配时的效率。
- 减少捕获组:尽量减少不必要的捕获组,在本示例中,只需要捕获
<span>
标签内的文本,所以只使用了一个捕获组 (.*?)
,避免过多捕获组带来的性能开销。