0

我有许多必须从网站上抓取的 URL。从捆绑文件中获取它们后,我创建了一个包含许多 URL 的数组。我将这个数组传递给我的名为 scrapeSanatcilar 的函数,并在那里添加了完成处理程序,但出现了问题。我只想在数组填充数据后从数组中获取一些随机元素:(

我在 viewdidLoad 中调用了 scrapeWithPage。

func scrapeWithPage(){
    
    let path = Bundle.main.path(forResource: "SanatciLink", ofType: "txt")!
    let text = try! String(contentsOfFile: path, encoding: String.Encoding.utf8)
    var links = text.components(separatedBy: CharacterSet.newlines)
    links.removeLast()
    
    scrapSanatcilar(links: links) { (result) in
        
        print(result.randomElement())
    }
    
}
    func scrapeSanatcilar(links: [String], completionHandler: @escaping (_ result: [String]) -> Void){
    
    for link in links{
       
        let baseUrl = link
        let url = URL(string: baseUrl)!
        
        let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
            guard let data = data else {
            self.makeAlert(titleInput: "Hata!", messageInput: "Üzgünüz ancak bir sorun oluştu lütfen daha sonra tekrar deneyin")
            return
            }
            guard let htmlString = String(data: data, encoding: .utf8) else {
            self.makeAlert(titleInput: "Hata!", messageInput: "Üzgünüz ancak bir sorun oluştu lütfen daha sonra tekrar deneyin")
            return
            }

           guard let songs: Elements = try? SwiftSoup.parse(htmlString).getElementsByClass("artist-list") else {return}

                do{

                       let hrefs : Elements  = try songs.select("a")

                       for href in hrefs{

                           self.scrapeSanatciNameWithPageLinks.append(try href.text())
                           self.scrapeSarkiNameWithPageLinks.append(try href.attr("href"))
                           
                       }
                    
                    
                   }catch{

               }

        };task.resume()
        
    }
    
    completionHandler(self.scrapeSanatciNameWithPageLinks)
    
}
4

2 回答 2

0

请将您的 completionHandler 移到您的 Task 中,因为异步是这样的:

func scrapeSanatcilar(links: [String], completionHandler: @escaping (_ result: [String]) -> Void){
        
        for link in links{
           
            let baseUrl = link
            let url = URL(string: baseUrl)!
            
            let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
                guard let data = data else {
                self.makeAlert(titleInput: "Hata!", messageInput: "Üzgünüz ancak bir sorun oluştu lütfen daha sonra tekrar deneyin")
                return
                }
                guard let htmlString = String(data: data, encoding: .utf8) else {
                self.makeAlert(titleInput: "Hata!", messageInput: "Üzgünüz ancak bir sorun oluştu lütfen daha sonra tekrar deneyin")
                return
                }
    
               guard let songs: Elements = try? SwiftSoup.parse(htmlString).getElementsByClass("artist-list") else {return}
    
                    do{
    
                           let hrefs : Elements  = try songs.select("a")
    
                           for href in hrefs{
    
                               self.scrapeSanatciNameWithPageLinks.append(try href.text())
                               self.scrapeSarkiNameWithPageLinks.append(try href.attr("href"))
                               
                           }

                        completionHandler(self.scrapeSanatciNameWithPageLinks)
                        
                       }catch{
    
                   }
    
            };task.resume()
            
        }
    }
于 2020-11-03T12:43:05.877 回答
0

您可以使用 DispatcGroup 来实现。当您想将一组任务作为一个单元进行监控时,可以使用 DispatchGroup。您可以分派多个异步任务,并在所有任务完成时收到通知。文档。

func scrapeSanatcilar(links: [String], completionHandler: @escaping (_ result: [String]) -> Void){
    //Here we create a group
    let group = DispatchGroup()
    
    
    for link in links{
        
        let baseUrl = link
        let url = URL(string: baseUrl)!
        
        
        group.enter()//Here we are saying to the group a new request is starting.
        let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
            defer {
                group.leave() //Defer is execute when the escope is finished. We call group.leave to notify our group this request is finished.
            }
            guard let data = data else {
                self.makeAlert(titleInput: "Hata!", messageInput: "Üzgünüz ancak bir sorun oluştu lütfen daha sonra tekrar deneyin")
                return
            }
            guard let htmlString = String(data: data, encoding: .utf8) else {
                self.makeAlert(titleInput: "Hata!", messageInput: "Üzgünüz ancak bir sorun oluştu lütfen daha sonra tekrar deneyin")
                return
            }
            
            guard let songs: Elements = try? SwiftSoup.parse(htmlString).getElementsByClass("artist-list") else {return}
            
            do{
                
                let hrefs : Elements  = try songs.select("a")
                
                for href in hrefs{
                    
                    self.scrapeSanatciNameWithPageLinks.append(try href.text())
                    self.scrapeSarkiNameWithPageLinks.append(try href.attr("href"))
                    
                }
                
                
            }catch{
                
            }
            
        }
        task.resume()
        
    }
    
    
    //When all request are finished this clousure will be execute notifying the main thread. Here you can call your completion handler
    group.notify(queue: .main) { [self] in
        completionHandler(self.scrapeSanatciNameWithPageLinks)
    }
    
    
    
    
    
}
于 2020-11-03T12:56:35.387 回答