使用Swift提取Nimiq钱包网页中的余额值
Alright, let's tackle this Nimiq wallet balance extraction problem you're facing. Right now you're pulling down the full HTML, but we need to parse that to grab the specific balance value from the <span> element you mentioned. Here's how to do it properly:
First, Understand the Page Structure
First, you'll need to identify the exact CSS selector for that balance <span>. Open your browser, navigate to the wallet page, right-click the balance element (the one showing "34...") and select Inspect. Once the dev tools open, right-click the <span> element in the DOM and choose Copy > Copy CSS Selector. This gives you a precise selector to target the element.
Option 1: Parse Static HTML with SwiftSoup
If the page renders the balance directly in the server-sent HTML (not loaded dynamically via JavaScript), you can use a HTML parsing library like SwiftSoup to extract the value cleanly (avoid messy string matching that breaks easily if the page changes).
Step 1: Add SwiftSoup
Add the SwiftSoup library to your project via Swift Package Manager or CocoaPods:
- For SPM: Add the package dependency in Xcode (search for "SwiftSoup" or use the official repository details)
- For CocoaPods: Add
pod 'SwiftSoup'to your Podfile and runpod install
Step 2: Code Implementation
import SwiftSoup func fetchNimiqBalance(for address: String) async throws -> String? { // Build the full URL let urlString = "https://nimiq.watch/#\(address)" guard let url = URL(string: urlString) else { throw NSError(domain: "WalletError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Invalid wallet address URL"]) } // Fetch HTML content (handle errors properly instead of force-unwrapping) let htmlContent = try String(contentsOf: url) // Parse the HTML document let doc = try SwiftSoup.parse(htmlContent) // Replace this selector with the one you copied from your browser guard let balanceElement = try doc.select("span.your-balance-class").first() else { return nil // Balance element not found } // Extract the text content of the span let balanceText = try balanceElement.text() return balanceText } // Usage example let targetAddress = "NQ48+8CKH+BA24+2VR3+N249+N8MN+J5XX+74DB+5XJ8" Task { do { if let balance = try await fetchNimiqBalance(for: targetAddress) { print("Wallet Balance: \(balance)") } else { print("Could not locate the balance element on the page.") } } catch { print("Error fetching balance: \(error.localizedDescription)") } }
Option 2: Handle Dynamic Content with WKWebView
If the balance is loaded dynamically via JavaScript (meaning the initial HTML you fetch doesn't contain the balance <span>), you'll need to use WKWebView to fully render the page and execute JavaScript to extract the value.
Code Implementation
import WebKit func fetchDynamicNimiqBalance(for address: String, completion: @escaping (Result<String?, Error>) -> Void) { let urlString = "https://nimiq.watch/#\(address)" guard let url = URL(string: urlString) else { completion(.failure(NSError(domain: "WalletError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Invalid wallet address URL"]))) return } // Initialize WKWebView and set up navigation delegate let webView = WKWebView() webView.navigationDelegate = BalanceNavigationDelegate(completion: completion) webView.load(URLRequest(url: url)) } // Delegate to handle page load completion class BalanceNavigationDelegate: NSObject, WKNavigationDelegate { private let completion: (Result<String?, Error>) -> Void init(completion: @escaping (Result<String?, Error>) -> Void) { self.completion = completion super.init() } func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { // Execute JavaScript to get the balance text (replace the selector with your copied one) webView.evaluateJavaScript("document.querySelector('span.your-balance-class').textContent") { result, error in if let error = error { self.completion(.failure(error)) return } // Cast the result to a string and return it let balanceText = result as? String self.completion(.success(balanceText)) } } func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { completion(.failure(error)) } } // Usage example let targetAddress = "NQ48+8CKH+BA24+2VR3+N249+N8MN+J5XX+74DB+5XJ8" fetchDynamicNimiqBalance(for: targetAddress) { result in switch result { case .success(let balance): if let balance = balance { print("Wallet Balance: \(balance)") } else { print("Balance element not found after page load.") } case .failure(let error): print("Error: \(error.localizedDescription)") } }
Key Notes
- Replace the Selector: Make sure to swap out
span.your-balance-classwith the actual CSS selector you copied from your browser. This is critical—without the right selector, the code won't find the balance. - Avoid Force Unwrapping: Your original code uses
myURL!which can crash if the URL is invalid. Always useguard letorif letto safely handle optional values. - Error Handling: Both examples include proper error handling to catch network issues, parsing errors, or missing elements.
内容的提问来源于stack exchange,提问作者Lyres

