Swift求助:如何快速将大量长HTML格式消息转为纯文本?
快速将HTML转换为纯文本的Swift解决方案
你当前使用NSAttributedString解析HTML的方式,底层依赖WebKit引擎,处理大量长文本时性能开销极大。以下是两种更高效的纯文本提取方案:
方法1:XMLParser原生解析(推荐,可靠且高效)
利用系统原生的XMLParser(HTML可兼容XML解析),逐节点提取文本内容,避免WebKit的重量级解析流程,适合复杂HTML结构的批量处理。
extension String { func htmlToPlainText() -> String { let parser = XMLParser(data: self.data(using: .utf8) ?? Data()) let delegate = HTMLTextParserDelegate() parser.delegate = delegate parser.parse() return delegate.plainText.trimmingCharacters(in: .whitespacesAndNewlines) } } class HTMLTextParserDelegate: NSObject, XMLParserDelegate { private(set) var plainText = "" func parser(_ parser: XMLParser, foundCharacters string: String) { let trimmed = string.trimmingCharacters(in: .whitespacesAndNewlines) if !trimmed.isEmpty { plainText += trimmed + " " } } // 处理换行标签,保留文本换行逻辑 func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) { if elementName.lowercased() == "br" || elementName.lowercased() == "p" { plainText += "\n" } } }
使用示例:
let htmlContent = "<p>这是一段<b>带格式</b>的HTML消息<br>第二行内容</p>" let plainText = htmlContent.htmlToPlainText() // 输出:"这是一段 带格式 的HTML消息\n第二行内容"
方法2:正则表达式快速清理(适合简单HTML场景)
如果你的HTML结构简单(无复杂嵌套、无特殊实体),可以用正则直接替换所有HTML标签,速度最快。
extension String { func simpleHtmlToPlainText() -> String { // 移除所有HTML标签 let tagRegex = try? NSRegularExpression(pattern: "<[^>]+>", options: .caseInsensitive) let tagFreeText = tagRegex?.stringByReplacingMatches( in: self, options: [], range: NSRange(location: 0, length: self.utf16.count), withTemplate: "" ) ?? self // 替换常见HTML实体 return tagFreeText .replacingOccurrences(of: "&", with: "&") .replacingOccurrences(of: "<", with: "<") .replacingOccurrences(of: ">", with: ">") .replacingOccurrences(of: """, with: "\"") .trimmingCharacters(in: .whitespacesAndNewlines) } }
使用示例:
let simpleHtml = "<div>简单<b>加粗</b>内容</div>" let plainText = simpleHtml.simpleHtmlToPlainText() // 输出:"简单加粗内容"
额外优化建议
- 后台队列处理:把解析逻辑放到后台队列执行,避免阻塞主线程:
func processHtmlToPlainText(_ html: String, completion: @escaping (String) -> Void) { DispatchQueue.global(qos: .background).async { let result = html.htmlToPlainText() DispatchQueue.main.async { completion(result) } } }
- 缓存结果:如果同一HTML内容会重复处理,建议缓存转换后的纯文本,减少重复计算。
内容的提问来源于stack exchange,提问作者Marta Paniti
相关产品推荐
相关产品推荐

