You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在macOS中通过Swift从网页及Safari页面提取指定文本?

macOS下Swift获取网页文本及Safari页面特定字符串提取方案

针对你提出的两个问题,结合你遇到的webView.webFrame.frameElement.innerText赋值label无效的问题,我整理了基于现代WebKit框架(WKWebView)的可行解决方案——毕竟旧的NSWebView已经被官方弃用,兼容性和稳定性都远不如WKWebView。


1. 在macOS中通过Swift获取网页文本

核心思路

用WKWebView(WebKit的现代组件)加载网页,等页面完全加载后,通过evaluateJavaScript执行JS代码抓取网页文本,最后必须在主线程更新UI控件——这很可能是你之前赋值无效的关键原因。

完整代码示例

import Cocoa
import WebKit

class ViewController: NSViewController, WKNavigationDelegate {
    
    var webView: WKWebView!
    @IBOutlet weak var pageContentLabel: NSTextField! // 用于显示网页文本的Label
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 初始化WKWebView并添加到视图
        let webConfig = WKWebViewConfiguration()
        webView = WKWebView(frame: view.bounds, configuration: webConfig)
        webView.navigationDelegate = self // 设置代理监听加载状态
        view.addSubview(webView)
        
        // 加载目标网页(这里以example.com为例,也可以加载本地HTML文件)
        guard let targetUrl = URL(string: "https://example.com") else {
            print("无效的URL")
            return
        }
        webView.load(URLRequest(url: targetUrl))
    }
    
    // 网页加载完成后触发的代理方法
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        // 执行JS获取整个网页的文本内容
        webView.evaluateJavaScript("document.documentElement.innerText") { [weak self] (result, error) in
            guard let self = self, let pageText = result as? String, error == nil else {
                print("获取网页文本失败: \(error?.localizedDescription ?? "未知错误")")
                return
            }
            
            // 必须在主线程更新UI,否则Label不会显示内容
            DispatchQueue.main.async {
                self.pageContentLabel.stringValue = pageText
            }
        }
    }
}

2. 在Safari页面(或任意网页)中提取特定字符串(如"Simple Text Example...")

两种提取方式

方式一:通过DOM元素定位提取(精准)

如果目标字符串在固定的DOM元素中(比如某个class或id的标签里),可以直接通过JS定位该元素并获取文本。假设你的HTML结构如下:

<!DOCTYPE html>
<html>
<head>
    <title>Test Page</title>
</head>
<body>
    <div class="target-section">Simple Text Example... This is the content we need.</div>
    <p>Other irrelevant content</p>
</body>
</html>

对应的Swift代码(放在webView(_:didFinish:)方法中):

webView.evaluateJavaScript("document.querySelector('.target-section').innerText") { [weak self] (result, error) in
    guard let self = self, let targetText = result as? String, error == nil else {
        print("提取目标文本失败: \(error?.localizedDescription ?? "未知错误")")
        return
    }
    
    DispatchQueue.main.async {
        // 更新Label显示提取到的内容
        self.pageContentLabel.stringValue = targetText
    }
}

方式二:通过正则表达式全局匹配(灵活)

如果目标字符串没有固定的DOM容器,可以先获取整个网页文本,再用正则表达式匹配提取:

// 放在webView(_:didFinish:)方法中
webView.evaluateJavaScript("document.documentElement.innerText") { [weak self] (result, error) in
    guard let self = self, let pageText = result as? String, error == nil else {
        print("获取网页文本失败")
        return
    }
    
    // 正则匹配以"Simple Text Example..."开头的内容
    let regexPattern = #"Simple Text Example.*"#
    guard let regex = try? NSRegularExpression(pattern: regexPattern, options: .dotMatchesLineSeparators) else {
        print("正则表达式创建失败")
        return
    }
    
    let textRange = NSRange(pageText.startIndex..., in: pageText)
    if let matchResult = regex.firstMatch(in: pageText, options: [], range: textRange) {
        let extractedText = String(pageText[Range(matchResult.range, in: pageText)!])
        DispatchQueue.main.async {
            self.pageContentLabel.stringValue = extractedText
        }
    } else {
        print("未找到目标字符串")
    }
}

关于你之前代码无效的原因分析

你使用的webView.webFrame.frameElement.innerText是旧NSWebView的API,现在已经被官方弃用,出现无效问题通常是这几个原因:

  1. 网页未完全加载:你可能在页面还没加载完成时就调用了该方法,导致获取到空值;
  2. 未在主线程更新UI:UI控件的更新必须在主线程执行,直接赋值不会生效;
  3. API兼容性问题:旧的NSWebView在新版本macOS中存在兼容性bug,官方推荐使用WKWebView替代。

内容的提问来源于stack exchange,提问作者dàhóngpáo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:55:40