如何使用Swift 4与Alamofire从无文档API抓取数据?
处理无文档校园API的数据获取问题
看起来你正在尝试从SRM University的evarsity系统抓取考勤和课表数据,这类无文档的内部API通常依赖会话认证(登录态靠Cookie维护),你的现有代码只做了基础的GET请求,大概率会返回未授权的结果。我来帮你梳理关键逻辑并完善代码:
1. 先搞定会话认证
首先必须完成登录流程,拿到有效的会话Cookie,后续所有数据请求都需要带上这个Cookie才能通过权限校验。你的URL_MAIN是登录页面,但登录动作一般是POST提交账号密码,而非简单的GET请求。
2. 完善后的代码示例
我把你未完成的代码补全,同时加入会话管理的核心逻辑:
import Alamofire // 定义API地址 let URL_LOGIN = "http://evarsity.srmuniv.ac.in/srmswi/usermanager/youLogin.jsp" let URL_ATTENDANCE = "http://evarsity.srmuniv.ac.in/srmswi/resource/StudentDetailsResources.jsp?resourceid=7" let URL_TIMETABLE = "http://evarsity.srmuniv.ac.in/srmswi/resource/StudentDetailsResources.jsp?resourceid=5" // 创建全局会话管理器,自动维护Cookie let sessionManager = Session.default func login(username: String, password: String, completion: @escaping (Bool) -> Void) { // 这里需要抓包确认登录表单的实际字段(比如可能有隐藏的token、csrf参数) let loginParams: [String: Any] = [ "userName": username, "password": password, "submit": "Login" ] sessionManager.request(URL_LOGIN, method: .post, parameters: loginParams) .responseString { response in switch response.result { case .success(let htmlContent): // 通过页面特征判断是否登录成功(比如包含"Welcome"或学生姓名) let isLoggedIn = htmlContent.contains("Welcome") completion(isLoggedIn) case .failure(let error): print("登录请求失败: \(error.localizedDescription)") completion(false) } } } func fetchData(from url: String, completion: @escaping (Data?, Error?) -> Void) { // 使用同一个会话管理器,自动携带登录后的Cookie sessionManager.request(url, method: .get) .responseData { response in switch response.result { case .success(let data): completion(data, nil) case .failure(let error): completion(nil, error) } } } // 使用示例 login(username: "你的学号", password: "你的密码") { success in if success { print("登录成功,开始获取数据") // 获取考勤数据 fetchData(from: URL_ATTENDANCE) { data, error in if let data = data { let htmlString = String(data: data, encoding: .utf8) print("考勤原始HTML:\(htmlString ?? "编码失败")") // 后续可以用SwiftSoup等库解析HTML提取有效数据 } else if let error = error { print("获取考勤失败: \(error.localizedDescription)") } } // 获取课表数据 fetchData(from: URL_TIMETABLE) { data, error in if let data = data { let htmlString = String(data: data, encoding: .utf8) print("课表原始HTML:\(htmlString ?? "编码失败")") } else if let error = error { print("获取课表失败: \(error.localizedDescription)") } } } else { print("登录失败,请检查账号密码或表单参数") } }
3. 关键注意事项
- 抓包分析请求细节:因为是无文档API,必须用Charles或浏览器开发者工具抓包,确认:
- 登录请求的完整表单字段(比如是否有
_csrf、token这类隐藏参数) - 响应中Cookie的具体名称,确保会话管理器正确保存
- 登录请求的完整表单字段(比如是否有
- HTML解析工具:这些API返回的是HTML页面而非JSON,建议用
SwiftSoup库来解析提取结构化数据 - 模拟浏览器请求:部分系统会校验User-Agent,记得在请求中添加合理的浏览器标识:
let headers: HTTPHeaders = [ "User-Agent": "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" ] // 在request方法中加入headers参数即可
内容的提问来源于stack exchange,提问作者Rish
相关产品推荐
相关产品推荐

