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

如何通过Tumblr API的GDPR验证并获取JSON数据?

解决Tumblr API请求返回GDPR HTML而非JSON的Swift实现方案

这个问题我之前踩过坑!Tumblr的GDPR隐私政策弹窗会拦截未验证的API请求——网页端点击「OK」本质是让浏览器存储了一个标记“已同意”的Cookie,后续请求就能正常拿到JSON;但直接用Swift发起请求时,因为没有这个Cookie,服务器就返回了带弹窗的HTML。下面给你两种可行的解决思路:

方法一:手动添加GDPR同意Cookie(推荐)

核心思路是:先抓包获取网页端点击「OK」后生成的GDPR相关Cookie,然后在Swift的网络请求里手动带上这个Cookie,让服务器认为你已经同意隐私政策。

步骤1:获取正确的Cookie值

用Chrome/Firefox的开发者工具抓包:

  • 打开http://demo.tumblr.com/api/read/json,点击弹窗的「OK」
  • 打开「开发者工具」→「Application」→「Cookies」→ 找到.tumblr.com域名下的GDPR相关Cookie(通常键名类似gdpr_consent,值是一串标识同意的字符串)
  • 复制这个Cookie的键值对,比如gdpr_consent=XXXXXX; path=/; domain=.tumblr.com

步骤2:修改Swift请求代码

把Cookie添加到请求头里,修改后的代码如下:

func makeReq() {
    guard let url = URL(string: "http://demo.tumblr.com/api/read/json") else { 
        print("URL格式错误")
        return 
    }
    
    // 构造带Cookie的请求
    var request = URLRequest(url: url)
    // 替换成你抓包得到的Cookie内容
    request.addValue("gdpr_consent=1; path=/; domain=.tumblr.com", forHTTPHeaderField: "Cookie")
    
    URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data, error == nil else {
            print("请求失败:\(error?.localizedDescription ?? "未知错误")")
            return
        }
        
        // 现在应该能拿到JSON数据了
        if let jsonString = String(data: data, encoding: .utf8) {
            print("获取到JSON:\(jsonString)")
            // 如果你需要在webView展示,也可以继续处理
            // DispatchQueue.main.async {
            //     self.webView.loadHTMLString(jsonString, baseURL: nil)
            // }
        }
    }.resume()
}

这种方法效率高,不需要依赖webView,只要Cookie有效就能一直用;缺点是如果Tumblr更新了Cookie规则,需要重新抓包更新。

方法二:模拟网页点击同意(兼容DOM变化)

如果不想抓包,也可以用webView加载页面,注入JavaScript模拟点击「OK」按钮,等Cookie设置完成后再发起API请求。

示例代码

import WebKit

class ViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler {
    var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 初始化带消息处理器的webView,用于接收JS回调
        let contentController = WKUserContentController()
        contentController.add(self, name: "fetchJSONAfterConsent")
        
        let config = WKWebViewConfiguration()
        config.userContentController = contentController
        
        webView = WKWebView(frame: view.bounds, configuration: config)
        webView.navigationDelegate = self
        view.addSubview(webView)
        
        // 开始加载页面处理GDPR
        handleGDPRConsent()
    }
    
    func handleGDPRConsent() {
        guard let url = URL(string: "http://demo.tumblr.com/api/read/json") else { return }
        webView.load(URLRequest(url: url))
    }
    
    // 页面加载完成后注入JS点击同意按钮
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        // 根据页面实际的按钮选择器调整,比如弹窗按钮的class或id
        let clickConsentJS = """
            // 尝试找到同意按钮并点击
            const consentBtn = document.querySelector('.gdpr-accept, .accept-btn, #gdpr-ok');
            if (consentBtn) {
                consentBtn.click();
                // 等待Cookie写入,1秒后通知原生代码发起请求
                setTimeout(() => {
                    window.webkit.messageHandlers.fetchJSONAfterConsent.postMessage('');
                }, 1000);
            } else {
                // 如果没有弹窗,直接通知原生请求
                window.webkit.messageHandlers.fetchJSONAfterConsent.postMessage('');
            }
        """
        
        webView.evaluateJavaScript(clickConsentJS) { result, error in
            if let error = error {
                print("执行JS出错:\(error.localizedDescription)")
            }
        }
    }
    
    // 接收JS的回调,发起API请求
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "fetchJSONAfterConsent" {
            guard let url = URL(string: "http://demo.tumblr.com/api/read/json") else { return }
            
            URLSession.shared.dataTask(with: url) { data, response, error in
                guard let data = data, error == nil else {
                    print("请求失败:\(error?.localizedDescription ?? "未知错误")")
                    return
                }
                
                if let jsonString = String(data: data, encoding: .utf8) {
                    print("获取到JSON:\(jsonString)")
                    // 后续处理逻辑
                }
            }.resume()
        }
    }
}

这种方法更贴近用户真实操作,不需要抓包,但缺点是依赖页面的DOM结构,如果Tumblr修改了弹窗的按钮样式或选择器,代码需要同步调整。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:11:38