快速加载网站以在不加载视图的情况下抓取代码 |网络套件

Posted

技术标签:

【中文标题】快速加载网站以在不加载视图的情况下抓取代码 |网络套件【英文标题】:Swift Load Website to Scrape Code Without Loading View | WebKit 【发布时间】:2020-04-10 03:48:43 【问题描述】:

我有一组 Google 新闻文章网址。 Google 新闻文章网址立即重定向到真实网址,即:CNBC.com/.... 我正在尝试提取真实的重定向网址。我以为我可以遍历列表并在 WebView 中加载 Google 新闻链接,然后在 1 秒后在 DispatchQueue 中调用 webView.url 以获取真正的 url,但这不起作用。

如何快速获取重定向网址列表?

这是我可以用来重现问题的代码:

        let webView = WKWebView()
        let myList = [URL(string: "https://news.google.com/articles/CAIiEDthIxbgofssGWTpXgeJXzwqGQgEKhAIACoHCAow2Nb3CjDivdcCMJ_d7gU?hl=en-US&gl=US&ceid=US%3Aen"), URL(string: "https://news.google.com/articles/CAIiEP5m1nAOPt-LIA4IWMOdB3MqGQgEKhAIACoHCAowocv1CjCSptoCMPrTpgU?hl=en-US&gl=US&ceid=US%3Aen")]

        for url in myList 
            guard let link = url else continue
            self.webView.loadUrl(string: link.absoluteString)

            DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) 
                let redirectedLink = self.webView.url
                print("HERE redirected url: ", redirectedLink) // this does not work
            
        

【问题讨论】:

从别人的网站上抓取内容是不是有点黏糊糊的? 最后我查了一下,这就是 Google 新闻的字面意思……一个大众聚合器/刮板。 聚合与抓取不同。 Google 新闻很可能是由 RSS 提要驱动的,当您点击标题时,您会转到创建该内容的网站。但是,当您抓取 Google 的页面时,您正在利用 Google 创建的内容并将其用作您自己的内容。谷歌拥有一百万种不同事物的 API,所以也许有一个用于他们汇总的新闻——如果是这样,使用它,你就不需要抓取任何东西。如果没有,那么也许您应该考虑选择自己的资源集。 【参考方案1】:

您的尝试有两个问题:

1) 您在循环中使用的是同一个 Web 视图,并且由于在 Web 视图完成加载之前循环内没有任何内容会阻塞,因此您最终会在每次循环通过时取消上一个请求。

2) 即使您确实在循环内阻塞,在一秒钟后访问 URL 也不会可靠地工作,因为导航很容易花费比这更长的时间。

我建议做的是继续使用单个 Web 视图(以节省资源),但使用其导航委托界面一个一个解析 URL。

这是一个粗略的例子,可以给你一个基本的想法:

import UIKit
import WebKit

@objc class RedirectResolver: NSObject, WKNavigationDelegate 

    private var urls: [URL]
    private var resolvedURLs = [URL]()
    private let completion: ([URL]) -> Void
    private let webView = WKWebView()

    init(urls: [URL], completion: @escaping ([URL]) -> Void) 
        self.urls = urls
        self.completion = completion
        super.init()
        webView.navigationDelegate = self
    

    func start() 
        resolveNext()
    

    private func resolveNext() 
        guard let url = urls.popLast() else 
            completion(resolvedURLs)
            return
        
        let request = URLRequest(url: url)
        webView.load(request)
    

    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) 
        resolvedURLs.append(webView.url!)
        resolveNext()
    




class ViewController: UIViewController 

    private var resolver: RedirectResolver!

    override func viewDidLoad() 
        super.viewDidLoad()

        resolver = RedirectResolver(
            urls: [URL(string: "https://news.google.com/articles/CAIiEDthIxbgofssGWTpXgeJXzwqGQgEKhAIACoHCAow2Nb3CjDivdcCMJ_d7gU?hl=en-US&gl=US&ceid=US%3Aen")!, URL(string: "https://news.google.com/articles/CAIiEP5m1nAOPt-LIA4IWMOdB3MqGQgEKhAIACoHCAowocv1CjCSptoCMPrTpgU?hl=en-US&gl=US&ceid=US%3Aen")!],
            completion:  urls in
                print(urls)
            )
        resolver.start()
    


这会输出以下已解析的 URL:

[https://amp.cnn.com/cnn/2020/04/09/politics/trump-coronavirus-tests/index.html, https://www.cnbc.com/amp/2020/04/10/asia-markets-coronavirus-china-inflation-data-currencies-in-focus.html]

要注意的另一件事是,这些 URL 的重定向尤其依赖于 javascript,这意味着您确实需要 Web 视图。否则手动启动URLRequests 并观察响应就足够了。

【讨论】:

以上是关于快速加载网站以在不加载视图的情况下抓取代码 |网络套件的主要内容,如果未能解决你的问题,请参考以下文章

如何在不加载视图的情况下重新加载/刷新部分视图中的级联下拉列表

在不重新加载整个表格视图的情况下更改 UITableView 的部分页眉/页脚标题

如何在不重新加载页面的情况下运行我的视图功能? [关闭]

如何在不使用视图控制器的情况下使用 nib 文件加载视图

在不重新加载活动的情况下更新回收站视图中的内容

在不加载 .mat 文件的情况下检查变量是不是在 .mat 文件中的快速方法? 'who'/'whos' 并不比加载快.. 比 'who' 更好的选择?