从字符串优化中提取链接

我从网站获取数据(HTML字符串)。 我想提取所有链接。 我写函数(它有效),但它太慢了……

你能帮我优化一下吗? 我可以使用哪些标准function? function逻辑:在文本中找到“http:.//”sting,然后读取字符串(购买字符)直到我不会得到“\”“。

extension String { subscript (i: Int) -> Character { return self[advance(self.startIndex, i)] } subscript (i: Int) -> String { return String(self[i] as Character) } subscript (r: Range) -> String { return substringWithRange(Range(start: advance(startIndex, r.startIndex), end: advance(startIndex, r.endIndex))) }} func extractAllLinks(text:String) -> Array{ var stringArray = Array() var find = "http://" as String for (var i = countElements(find); i<countElements(text); i++) { var ch:Character = text[i - Int(countElements(find))] if (ch == find[0]) { var j = 0 while (ch == find[j]) { var ch2:Character = find[j] if(countElements(find)-1 == j) { break } j++ i++ ch = text[i - Int(countElements(find))] } i -= j if (j == (countElements(find)-1)) { var str = "" for (; text[i - Int(countElements(find))] != "\""; i++) { str += text[i - Int(countElements(find))] } stringArray.append(str) } } } return stringArray} 

就像上面使用NSDataDetector所述的NSDataDetector您可以轻松获取所有URL,请参阅以下代码:

 let text = "http://www.google.com. http://www.bla.com" let types: NSTextCheckingType = .Link var error : NSError? let detector = NSDataDetector(types: types.rawValue, error: &error) var matches = detector!.matchesInString(text, options: nil, range: NSMakeRange(0, count(text))) for match in matches { println(match.URL!) } 

它输出:

 http://www.google.com http://www.bla.com 

已更新至Swift 2.0

 let text = "http://www.google.com. http://www.bla.com" let types: NSTextCheckingType = .Link let detector = try? NSDataDetector(types: types.rawValue) guard let detect = detector else { return } let matches = detect.matchesInString(text, options: .ReportCompletion, range: NSMakeRange(0, text.characters.count)) for match in matches { print(match.URL!) } 

记得在上面的情况下使用guard语句它必须在函数或循环中。

我希望这有帮助。

非常有用的线程! 这是根据Victor Sigler的回答在Swift 1.2中运行的一个例子。

  // extract first link (if available) and open it! let text = "How technology is changing our relationships to each other: http://t.ted.com/mzRtRfX" let types: NSTextCheckingType = .Link do { let detector = try NSDataDetector(types: types.rawValue) let matches = detector.matchesInString(text, options: .ReportCompletion, range: NSMakeRange(0, text.characters.count)) if matches.count > 0 { let url = matches[0].URL! print("Opening URL: \(url)") UIApplication.sharedApplication().openURL(url) } } catch { // none found or some other issue print ("error in findAndOpenURL detector") } 

这就是Swift 4.0的答案

 let text = "http://www.google.com. http://www.bla.com" let types: NSTextCheckingResult.CheckingType = .link let detector = try? NSDataDetector(types: types.rawValue) guard let detect = detector else { return } let matches = detect.matches(in: content, options: .reportCompletion, range: NSMakeRange(0, content.count)) for match in matches { print(match.url!) } 

实际上有一个名为NSDataDetector的类会为您检测链接。

您可以在NSHipster上找到它的示例: http ://nshipster.com/nsdatadetector/

我想知道你是否意识到每次调用countElements时,都会调用一个主要的复杂函数,它必须扫描字符串中的所有Unicode字符,并从中提取扩展的字形集群并对它们进行计数。 如果你不知道扩展的字形集群是什么,那么你应该能够想象这不是便宜且重大的过度杀伤力。

只需将其转换为NSString *,调用rangeOfString并完成它。

显然你做的是完全不安全的,因为http://并不意味着有一个链接。 你不能只在html中查找字符串并希望它有效; 它没有。 然后有https,Http,hTtp,htTp,httP等等等等等。 但这很容易,因为真正的恐怖跟随Uttam Sinha评论中的链接。

正如其他人指出的那样,最好使用正则表达式,数据检测器或解析库。 但是,作为字符串处理的具体反馈:

Swift字符串的关键是拥抱它们的前向性。 通常,整数索引和随机访问不是必需的。 正如@ gnasher729指出的那样,每次调用count都会迭代字符串。 类似地,整数索引扩展是线性的,因此如果在循环中使用它们,则很容易意外地创建二次或三次复杂度算法。

但在这种情况下,没有必要做所有工作将字符串索引转换为随机访问整数。 这是一个我认为执行类似逻辑的版本(寻找一个前缀,然后从那里看一个“字符 – 忽略这不适合https,大写/小写等)仅使用本机字符串索引:

 func extractAllLinks(text: String) -> [String] { var links: [String] = [] let prefix = "http://" let prefixLen = count(prefix) for var idx = text.startIndex; idx != text.endIndex; ++idx { let candidate = text[idx.. 

即使这可以进一步优化( advance(idx, count())有点低效)如果有其他帮助程序,如findFromIndex等,或者愿意没有字符串切片,并手动搜索结束字符。