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

Swift解析PHP网页失败求助:http://www.ggjh.co.kr/now/menu.php

问题分析与解决方案

首先可以拍板说:.php后缀绝对不是问题——PHP只是后端运行的脚本,最终返回给客户端的还是标准的HTML文本,和静态.html页面没有本质区别。你的解析失败大概率是以下几个常见原因导致的,咱们逐一排查解决:

1. 先排查ATS(App Transport Security)限制

iOS默认禁止HTTP明文请求(只允许HTTPS),而你访问的是http://www.ggjh.co.kr(HTTP协议),这会被ATS直接拦截,这是最常见的触发点!

解决方法:

在Info.plist中添加ATS例外配置:
右键点击Info.plist → 选择Open As → Source Code,插入以下代码:

<key>NSAppTransportSecurity</key>
<dict>
    <!-- 更安全的做法:只允许目标域名的HTTP请求 -->
    <key>NSExceptionDomains</key>
    <dict>
        <key>ggjh.co.kr</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict>
    </dict>
    <!-- 全局允许HTTP(不推荐,仅用于测试) -->
    <!-- <key>NSAllowsArbitraryLoads</key>
    <true/> -->
</dict>

优先推荐特定域名例外的配置,比全局允许更安全。

2. 非UTF-8编码导致解析乱码/失败

韩语网站常用EUC-KR编码,而Swift的String(contentsOf:)默认用UTF-8解析,编码不匹配会直接导致内容乱码或者解析失败。

解决方法:手动指定编码解析

fileprivate func parseMenuHtml(){ 
    guard let url = URL(string: "http://www.ggjh.co.kr/now/menu.php") else {
        print("URL格式错误")
        return
    }
    
    do { 
        let data = try Data(contentsOf: url)
        // 优先尝试韩语常用的EUC-KR编码
        if let contents = String(data: data, encoding: .eucKR) {
            print(contents)
            // 用Kanna解析HTML
            if let doc = try? HTML(html: contents, encoding: .eucKR) {
                // 替换成目标页面实际的CSS选择器,比如查找菜单元素
                let menuItems = doc.css(".menu-item")
                for item in menuItems {
                    print(item.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "")
                }
            }
        } else {
            //  fallback到UTF-8编码
            if let contents = String(data: data, encoding: .utf8) {
                print(contents)
            } else {
                print("无法识别页面编码")
            }
        }
    } catch { 
        // 打印具体错误,不要只输出"error"!
        print("请求/解析错误: \(error.localizedDescription)")
    } 
}

3. 服务器需要自定义请求头

部分服务器会检查请求的User-Agent等头信息,String(contentsOf:)的默认请求头过于简单,可能被服务器拒绝返回内容。

解决方法:用URLSession自定义请求头

fileprivate func parseMenuHtml(){ 
    guard let url = URL(string: "http://www.ggjh.co.kr/now/menu.php") else {
        print("URL格式错误")
        return
    }
    
    var request = URLRequest(url: url)
    // 模拟浏览器的User-Agent
    request.setValue("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36", forHTTPHeaderField: "User-Agent")
    // 添加Accept头,告诉服务器接收HTML格式
    request.setValue("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", forHTTPHeaderField: "Accept")
    
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        if let error = error {
            print("请求错误: \(error.localizedDescription)")
            return
        }
        guard let data = data else {
            print("服务器未返回数据")
            return
        }
        
        // 编码处理逻辑同上面的示例
        if let contents = String(data: data, encoding: .eucKR) {
            print(contents)
            // 如果要更新UI,记得切回主线程
            DispatchQueue.main.async {
                if let doc = try? HTML(html: contents, encoding: .eucKR) {
                    // 执行你的解析逻辑
                }
            }
        }
    }
    task.resume()
}

关键提示:不要忽略错误信息

你之前的代码只打印"error",这完全无法定位问题!一定要打印error.localizedDescription或者直接打印error本身,这样才能知道是ATS拦截、网络超时还是编码错误。

内容的提问来源于stack exchange,提问作者Tolerance

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:53:56