Google Search with Alamofire Fails (iOS, Swift, JSON, HTML)
Please help! I'm stuck for months now trying to perform a simple Google Search on my Swift App and I'm way past smashing my head through the wall!
I've tried both with ALAMOFIRE and With a Regular URLRequest, but since the result seems to be only in HTML Format, I Can't seem to parse the results correctly. Even when you look into the HTML Format, the code is for a Webpage, and it does NOT Include the Search Results.
I Would LOVE to have the search Results into a Simple Dictionary. Here is my Code:
let googleUrl:String = "https://cse.google.com/cse/publicurl?&output=json&cx=<MyGoogleKey>:<MyGoogleSKey>&q=q=+normal+search"
// Trying with AlamoFire:
Alamofire.request(googleUrl).response { response in
print("Request: (response.request)")
print("Response: (response.response)")
print("Error: (response.error)")
}.responseJSON(completionHandler: { response in
print("ResponseJSON: (response)")
}).responseData(completionHandler: { response in
print("ResponseData: (response)")
}).responseString(completionHandler: { response in
print("ResponseString: (response)")
})
As you See I Try the Response in almost ALL Alamofire supported Types and I GEt NOTHING.
Here is Error #1 (. responseJSON ):
The data couldn't be read because it isn't in the correct format. ResponseJSON: FAILURE: responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}))
Here is DATA Response (. responseData ): ResponseData: SUCCESS: 4337 bytes
Here is the Response HTML (. responseString )
ResponseString: SUCCESS:
*> Google Custom Search
(function(){var cookie_path='/cse/';var path_copy='/coop/';window._gaq = window._ga...._AND_SO_ON_TILL_FULL_HTML_PAGE_IN_A_STRING....*
* I Only wish I Could have the Search Results in a Simple Dictionary...
Anyone? Please?
You seem to be using the Custom Search API for embedding into web pages.
This documentation is for what you want to do.
Here is an example using stack overflow as the search domain.
import UIKit
import Alamofire
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
search(query: "swift") { (results) in
for result in results {
dump(result)
}
}
}
func search(query:String, completion: @escaping (Array<SearchResult>)->()){
let id = "Custom search engine ID"
let key = "API key"
let url = "https://www.googleapis.com/customsearch/v1?key=(key)&cx=(id)&q=(query)"
Alamofire.request(url).responseJSON { (response) in
var results = Array<SearchResult>()
if let dict = response.value as? Dictionary<String,Any> {
if let items = dict["items"] as? Array<Dictionary<String,Any>> {
for item in items {
if let result = SearchResult(dict: item) {
results.append(result)
} else {
print("Incomplete search result data.")
}
}
}
}
completion(results)
}
}
}
I have this struct to store the search results better. It doesn't contain all the values that the JSON results does. I just chose these ones for testing.
struct SearchResult {
var displayLink: String
var formattedUrl: String
var htmlFormattedUrl: String
var htmlSnippet: String
var htmlTitle: String
var link: String
var snippet: String
var title: String
init?(dict:Dictionary<String,Any>) {
guard
let displayLink = dict["displayLink"] as? String,
let formattedUrl = dict["formattedUrl"] as? String,
let htmlFormattedUrl = dict["htmlFormattedUrl"] as? String,
let htmlSnippet = dict["htmlSnippet"] as? String,
let htmlTitle = dict["htmlTitle"] as? String,
let link = dict["link"] as? String,
let snippet = dict["snippet"] as? String,
let title = dict["title"] as? String
else {
return nil
}
self.displayLink = displayLink
self.formattedUrl = formattedUrl
self.htmlFormattedUrl = htmlFormattedUrl
self.htmlSnippet = htmlSnippet
self.htmlTitle = htmlTitle
self.link = link
self.snippet = snippet
self.title = title
}
}
This is a couple of results that dump(result)
prints out.
▿ CustomGoogleSearch.SearchResult
- displayLink: "stackoverflow.com"
- formattedUrl: "https://stackoverflow.com/questions/tagged/swift"
- htmlFormattedUrl: "https://stackoverflow.com/questions/tagged/<b>swift</b>"
- htmlSnippet: "<b>Swift</b> is an open-source programming language developed by Apple. Use the tag <br>nonly for questions about language features, or requiring code in <b>Swift</b>. Use the ..."
- htmlTitle: "Newest '<b>swift</b>' Questions - Stack Overflow"
- link: "https://stackoverflow.com/questions/tagged/swift"
- snippet: "Swift is an open-source programming language developed by Apple. Use the tag nonly for questions about language features, or requiring code in Swift. Use the ..."
- title: "Newest 'swift' Questions - Stack Overflow"
▿ CustomGoogleSearch.SearchResult
- displayLink: "stackoverflow.com"
- formattedUrl: "stackoverflow.com/documentation/swift/topics"
- htmlFormattedUrl: "stackoverflow.com/documentation/<b>swift</b>/topics"
- htmlSnippet: "58 example-focused documentation topics for <b>Swift</b> Language."
- htmlTitle: "All <b>Swift</b> Language Topics - Stack Overflow"
- link: "http://stackoverflow.com/documentation/swift/topics"
- snippet: "58 example-focused documentation topics for Swift Language."
- title: "All Swift Language Topics - Stack Overflow"
Getting the keys
On this page, click the Get A Key
button.
You then need to select or create a Google project, then you will be generated an API Key. So copy this an put in here let key = "API key"
For the Search Engine ID, go to your console. Now either select a search engine or create a new one. You'll get to a page like this.
Click the Search engine ID
button, this will display a screen with your id, then put that here let id = "Custom search engine ID"
上一篇: 数组分配与追加行为