2017-08-24 53 views
0

您好我想創造與SWIFT 3的應用程序,允許用戶輸入自己的用戶名和密碼的文本字段,並按下登錄按鈕將登錄到這個網站:https://login.utexas.edu/login/UI/Login登錄網站迅速使用alamofire

我希望它能夠對用戶進行身份驗證並存儲令牌,以便我可以重定向到:https://utdirect.utexas.edu/registration/classlist.WBX 以獲取html併爲該課程刮取網頁。

@IBOutlet weak var uteid: UITextField! 
@IBOutlet weak var password: UITextField! 


    var parameter: Parameters = [:] 
    var requestID: String = "" 
    var sunQueryParamsString: String = "" 
    var hiddenFields: String = "" 

@IBAction func postRequest(_ sender: Any) { 

     let urlString = "https://utdirect.utexas.edu/registration/classlist.WBX" 
     Alamofire.request(urlString).responseString { response in 
      print("\(response.result.isSuccess)") 
      if let html = response.result.value { 
       if let doc = Kanna.HTML(html: html, encoding: String.Encoding.utf8) { 
        // Search for nodes by CSS selector 

        print("\nrequestID") 
        for show in doc.css("input[name='login_param_RequestID']") { 
         self.requestID=show["value"]! 
         print(show["value"] as Any) 
        } 

        print("\nsunQueryParamsString") 
        for show in doc.css("input[name='SunQueryParamsString']") { 
         self.sunQueryParamsString=show["value"]! 
         print(show["value"] as Any) 
        } 

        print("\nhiddenFields") 
        for show in doc.css("input[type='hidden']") { 
         self.hiddenFields=show["value"]! 
         print(show["value"] as Any) 
        } 
       } 
      } 

      //creating dictionary for parameters 
      self.parameter = [ 
       "login_uri":"/login/cdcservlet", 
       "login_param_RequestID":self.requestID, 
       "login_param_ProviderID":"https://utdirect.utexas.edu:443/amagent?Realm=/admin/utdirect-realm", 
       "goto":"https://utdirect.utexas.edu:443/registration/classlist.WBX", 
       "SunQueryParamsString":self.sunQueryParamsString, 
       "IDToken1": self.uteid.text!, 
       "IDToken2": self.password.text!, 
       "IDButton": "Submit" 
      ] 

      //Wait for the GET request to complete, and then send the POST request: <<== 
      Alamofire.request (urlString,method: .post, parameters: self.parameter).responseString { response in 
       print("\(response.result.isSuccess)") 
       print(response) 
      } 

     } 
} 
+1

這不是一個軟件交付網站。閱讀[here](https:// stackoverflow。com/help/how-to-ask)如何正確詢問 –

+0

@JoaoVitorino但我不知道如何使用alamofire登錄和驗證用戶,我找不到任何東西來幫助我 –

+0

首先發布你的代碼,您已經完成了解決問題的工作,您期望的輸出是什麼,並告訴發生了什麼問題。直到現在,您只是要求我們爲您的 –

回答

-1

不用說,請務必檢查您的網站的服務條款,以確保它們不會禁止許多網站進行刮擦。我還會聯繫網站的所有者,看看他們是否有可以與之互動的網絡服務,因爲搜索效率低下,脆弱且耗時。與Web服務交互會更容易。

如果您使用外部嗅探工具(如CharlesWireShark),並且在瀏覽器上登錄時會看到來回的內容,那麼編寫刮刀更容易。然後編寫您的應用程序來重現此問題,仔細比較您的應用程序請求和網站生成的響應。它還可以讓你識別他們是否使用AJAX,以及這些是什麼樣的。

您可能還想獲得HTML解析器,例如TFHppleNDHpple。當您請求一個頁面(例如登錄頁面)時,您可能需要解析HTML表單中的hidden字段,並將它們包含在後續的POST請求中。這可能是一種模式,你可能會做很多事情,所以適合解析隱藏字段的HTML可能會很有用。

底線,抓取過程通常需要請求某個頁面,解析它,然後創建下一個請求並重復。請留意AJAX,因爲可能會有請求超出您在網絡瀏覽器地址欄中看到的內容。


當你刮網站,很容易看的登錄頁面,說:「OK,我只需要用戶名和密碼發佈和我的黃金」。

事情是,它往往比這更復雜。你可能不認爲你需要擔心檢索登錄頁面的HTML,但你經常這樣做。有時,該登錄表單上有隱藏字段(需要解析出來)。有時它會設置cookie。這取決於。

就你而言,你的登錄頁面都可以。因此,使用TFHpple,你可以這樣做:

func retrieveLoginPageParameters(completion: @escaping ([String: String]?, Error?) -> Void) { 
    Alamofire.request("https://login.utexas.edu/login/UI/Login") 
     .responseData { response in 
      guard let data = response.data, response.error == nil else { 
       completion(nil, response.error) 
       return 
      } 

      let doc = TFHpple(htmlData: data) 
      guard let elements = doc?.search(withXPathQuery: "//input[@type='hidden']") as? [TFHppleElement] else { 
       fatalError("bad xpath") 
      } 

      var parameters = ["IDToken1": self.username, "IDToken2": self.password] 
      elements.forEach { element in 
        if let name = element.attributes["name"] as? String, 
         let value = element.attributes["value"] as? String { 
         parameters[name] = value 
        } 
      } 
      completion(parameters, nil) 
    } 
} 

檢索登錄頁面,並解析了隱藏字段。然後,您可以用它來登錄:

retrieveLoginPageParameters { parameters, error in 
    guard let parameters = parameters, error == nil else { 
     print(error?.localizedDescription ?? "Unknown error") 
     return 
    } 

    self.login(with: parameters) { success in 
     print(success ? "successful login" : "login failed") 
    } 
} 

func login(with parameters: [String: String], completion: @escaping (Bool) -> Void) { 
    Alamofire.request("https://login.utexas.edu/openam/UI/Login", method: .post, parameters: parameters) 
     .responseData { response in 
      guard let data = response.data, response.error == nil else { 
       print(response.error?.localizedDescription ?? "Unknown error") 
       return 
      } 

      // you can now parse the html to make sure login was successful 

      // when done, call completion handler indicating whether login 
      // was successful or not; given I don't know what a successful 
      // login looks like, I cannot go any further here 

      completion(true) 
    } 
} 

注意,我要送的登錄請求openam/UI/Login,因爲這是action<form>中使用的HTML。也許在成功登錄後重定向到其他頁面,但必須將登錄請求發送到登錄<form>HTML的同一頁面。

+0

感謝您的輸入!在抓取之前需要完成的第一步是登錄到網站並對用戶進行身份驗證,因爲要獲得班級列表,我必須先登錄。我打算使用其中一個HTML解析器,但是我在正確的軌道上嗎?或者我應該以不同的方式登錄? –

+0

您正在跳過一個步驟。您在發送登錄請求時未請求登錄HTML頁面。我知道,當它感覺只是顯示一個登錄表單時,要求登錄HTML頁面感覺很奇怪,但它確實有隱藏的字段和Cookie,當您使用憑據發送實際登錄信息時,您經常需要捕獲和包含這些字段和Cookie。 cookie應該被自動捕獲,但你必須自己手動捕獲隱藏的字段(這就是爲什麼我們使用HTML解析器)。 – Rob

+0

我明白了。在閱讀完本文後,我瞭解了一些:https://brennan.io/2016/03/02/logging-in-with-requests/ –