2017-10-20 20 views
1

Je suis en train d'analyser certains HTML pour tirer tous les liens qui viennent après toutes les occurrences de la chaîne:Essayer d'analyser HTML à Swift 4 en utilisant uniquement la bibliothèque standard

market_listing_row_link « href = »

pour rassembler une liste d'URL d'éléments en utilisant uniquement la bibliothèque standard Swift 4. Ce que je pense avoir besoin est une boucle for qui vérifie les caractères avec une condition qui une fois la chaîne complète est trouvée, il commence alors à lire l'URL de l'élément suivant dans un tableau jusqu'à ce qu'une double citation soit atteinte, s'arrêtant puis répéter ce processus jusqu'à la fin du fichier. Légèrement familier en C, nous avons eu accès à une fonction (je pense que c'était fgetc) qui l'a fait en avançant un indicateur de position pour le fichier. Existe-t-il une manière similaire de faire cela dans Swift?

Mon code jusqu'ici ne peut trouver la première occurrence de la chaîne que je cherche quand il y en a 10 que j'ai besoin de trouver.

import Foundation 

extension String { 
    func slice(from: String, to: String) -> String? { 
     return (range(of: from)?.upperBound).flatMap { substringFrom in 
      (range(of: to, range: substringFrom..<endIndex)?.lowerBound).map { substringTo in 
       String(self[substringFrom..<substringTo]) 
      } 
     } 
    } 
} 

let itemListURL = URL(string: "http://steamcommunity.com/market/search?appid=252490")! 
let itemListHTML = try String(contentsOf: itemListURL, encoding: .utf8) 
let itemURL = URL(string: itemListHTML.slice(from: "market_listing_row_link\" href=\"", to: "\"")!)! 

print(itemURL) 

// Prints the current first URL found matching: http://steamcommunity.com/market/listings/252490/Wyrm%20Chest 
+2

cela comme un commentaire au lieu d'une réponse, car elle ne répond pas directement à votre question. Avez-vous envisagé d'utiliser [XMLParser] (https://developer.apple.com/documentation/foundation/xmlparser) à la place? L'analyse syntaxique XML est généralement préférée aux manigances regex en matière de HTML (voir, par exemple, [cette fameuse réponse Stack Overflow.] (Https://stackoverflow.com/questions/1732348/regex-match-open-tags-except -xhtml-self-contained-tags/1732454 # 1732454) –

+1

@AlanKantz HTML n'est pas du code XML à moins qu'il ne s'agisse réellement de xHTML. – rmaddy

+0

@AlanKantz Oubliez que c'est du HTML, je veux rechercher une chaîne de non-sens pour une séquence de caractères, lire les caractères qui suivent cette séquence dans une variable chaîne jusqu'à un certain caractère et continuer à chercher une autre occurrence de cette séquence le processus. – ANoobSwiftly

Répondre

0

Vous pouvez utiliser regex pour trouver toutes les occurrences de chaîne entre deux chaînes spécifiques (cochez cette SO answer) et utiliser la méthode d'extension ranges(of:) de cette answer pour obtenir toutes les gammes de ce modèle de regex. Vous avez juste besoin de passer des options .regularExpression à cette méthode.


extension String { 
    func ranges(of string: String, options: CompareOptions = .literal) -> [Range<Index>] { 
     var result: [Range<Index>] = [] 
     var start = startIndex 
     while let range = range(of: string, options: options, range: start..<endIndex) { 
      result.append(range) 
      start = range.lowerBound < range.upperBound ? range.upperBound : index(range.lowerBound, offsetBy: 1, limitedBy: endIndex) ?? endIndex 
     } 
     return result 
    } 
    func slices(from: String, to: String) -> [Substring] { 
     let pattern = "(?<=" + from + ").*?(?=" + to + ")" 
     return ranges(of: pattern, options: .regularExpression) 
      .map{ self[$0] } 
    } 
} 

aire de jeux Test

let itemListURL = URL(string: "http://steamcommunity.com/market/search?appid=252490")! 
let itemListHTML = try! String(contentsOf: itemListURL, encoding: .utf8) 
let result = itemListHTML.slices(from: "market_listing_row_link\" href=\"", to: "\"") 
result.forEach({print($0)}) 

Résultat

http://steamcommunity.com/market/listings/252490/Night%20Howler%20AK47 http://steamcommunity.com/market/listings/252490/Hellcat%20SAR Je poste http://steamcommunity.com/market/listings/252490/Volcanic%20Stone%20Hatchet http://steamcommunity.com/market/listings/252490/Box http://steamcommunity.com/market/listings/252490/High%20Quality%20Bag http://steamcommunity.com/market/listings/252490/Utilizer%20Pants http://steamcommunity.com/market/listings/252490/Lizard%20Skull http://steamcommunity.com/market/listings/252490/Frost%20Wolf http://steamcommunity.com/market/listings/252490/Cloth

+0

N'oubliez pas d'utiliser URLSession dataTask pour récupérer les données html de votre URL de manière asynchrone –

+1

Ceci est parfait! Je vous remercie! – ANoobSwiftly