Swift中用SwiftSoup解析HTML到结构体并打印内容的方法
解决ASPX登录VIEWSTATE参数解析与打印问题
问题根源
现有代码存在两个核心问题:
NetworkingManager的request方法是异步执行的,解析出的viewstateToken仅存在于网络请求闭包内部,没有对外传递的渠道,导致ContentView无法获取并打印;- 结构体默认没有友好的打印格式,直接
print无法清晰展示参数内容。
解决方案
1. 给NetworkingManager添加回调闭包
修改request方法,新增completion回调来传递解析结果(成功返回viewstateToken,失败返回错误):
final class NetworkingManager { static let shared = NetworkingManager() private init() {} func request(_ absoluteURL: String, completion: @escaping (Result<viewstateToken, Error>) -> Void) { guard let url = URL(string: absoluteURL) else { completion(.failure(NSError(domain: "无效URL", code: -1, userInfo: nil))) return } let request = URLRequest(url: url) let dataTask = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { completion(.failure(error)) return } guard let response = response as? HTTPURLResponse, (200...300) ~= response.statusCode else { completion(.failure(NSError(domain: "HTTP响应异常", code: -2, userInfo: nil))) return } guard let data = data, let tempHTML = String(data: data, encoding: .utf8) else { completion(.failure(NSError(domain: "数据解析失败", code: -3, userInfo: nil))) return } do { let htmlDocument = try SwiftSoup.parse(tempHTML) // 避免重复解析HTML,提升效率 let viewState = try htmlDocument.select("input[name=__VIEWSTATE]").attr("value") let viewStateGenerator = try htmlDocument.select("input[name=__VIEWSTATEGENERATOR]").attr("value") let tokens = viewstateToken(viewState: viewState, viewStateGenerator: viewStateGenerator) completion(.success(tokens)) } catch { completion(.failure(error)) } } dataTask.resume() } }
2. 让viewstateToken支持友好打印
给结构体添加CustomStringConvertible协议,自定义打印格式:
struct viewstateToken: Identifiable, Hashable, Codable, CustomStringConvertible { let id = UUID() var viewState: String var viewStateGenerator: String var description: String { return "viewstateToken:\n viewState: \(viewState)\n viewStateGenerator: \(viewStateGenerator)\n id: \(id)" } }
3. 在ContentView中获取并打印tokens
修改onAppear中的调用逻辑,通过回调拿到结果并打印:
.onAppear { NetworkingManager.shared.request("https://examplelink.com") { result in switch result { case .success(let tokens): print(tokens) // 现在可以打印清晰的结构体内容 case .failure(let error): print("请求或解析错误:\(error)") } } }
额外优化点
- 替换了原代码中的强制解包(
try!、url!),改为安全的可选绑定和错误处理,避免运行时崩溃; - 只解析一次HTML文档,提升性能;
- 统一错误处理逻辑,通过回调返回所有可能的错误类型。
内容的提问来源于stack exchange,提问作者Sander
相关产品推荐
相关产品推荐

