如何通过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
相关产品推荐
相关产品推荐

