从WKWebView获取favicon.co

3

我正在使用新的wkWebView,用于OS X和iOS系统。为了将webview呈现为图标,我需要获取所呈现URL的favicon。在旧的webview中,我可以使用以下函数:

var mainFrameIcon: NSImage! { get }

使用Swift或Objective-C中的wkWebView如何获取图像?
3个回答

1
似乎新的WKWebView类没有任何公共内置图标,但是您可以轻松地检索到它。由于网站将favicon url存储在/favicon.ico上,因此您只需从web视图中获取主机url,添加/favicon.ico到末尾并将其作为nsimage获取即可。
请按以下方式执行:
NSURL *webpageURL = myWebView.URL;
NSString *hostURL = webpageURL.host;
NSString *faviconURL = [NSString stringWithFormat:@"http://%@/favicon.ico",hostURL];
NSImage *faviconImage = [[NSImage alloc] initWithContentsOfURL:[NSURL URLWithString:faviconURL]];

希望这有所帮助。

我对这种方法有点紧张。现在许多网站在其HTML中指定图标。此外,这种方法不使用https。 - Andrew Rondeau

1

像其他帖子中的许多人所说,现在找到一个网站的 favicon 并不是一件容易的事情。

因此,我开发了一个开源框架来为您处理繁重的工作。 https://github.com/will-lumley/FaviconFinder/


0

不幸的是,获取网站图标不再是一个简单的属性。原因是网站可以为不同的分辨率声明多个favicon。您(应用程序开发人员)需要为自己的需求选择适当的图标。

另一个复杂之处在于,您(应用程序开发人员)需要在WKWebView对象中执行JavaScript才能从链接标签中获取网站图标!

(注意:依赖/favicon.ico会出现错误。有些网站不更新其CMS的/favicon.ico,并仅通过链接标签设置它。在这种情况下,一个在Chrome中具有正确图标的页面可能会在您的自定义浏览器中显示Drupal图标。)

以下是解析链接标签的JavaScript以及进一步阅读结果的Swift代码。

// Based on code from  https://dev59.com/l2kv5IYBdhLWcg3w4kt3
static private var GET_FAVICON_SCRIPT = """
    var favicons = [];
    var nodeList = document.getElementsByTagName('link');
    for (var i = 0; i < nodeList.length; i++)
    {
        if((nodeList[i].getAttribute('rel') == 'icon')||(nodeList[i].getAttribute('rel') == 'shortcut icon'))
        {
            const node = nodeList[i];
            favicons.push({
                url: node.getAttribute('href'),
                sizes: node.getAttribute('sizes')
            });
        }
    }
    favicons;
"""

public private(set) var faviconUrls = Set<FaviconUrl>()

func updateFavicon() {
    self.webView.evaluateJavaScript(TabViewController.GET_FAVICON_SCRIPT) { (result, error) in
        // Favicon is returned from Javascript as an NSMutableArray with NSMutableDictionaries
        // Needs to be turned into a list
        var faviconUrls = Set<FaviconUrl>();

        // If the script returned correctly
        if let favicons = result as? NSArray {
            for faviconObject in favicons {
                if let faviconDictionary = faviconObject as? NSDictionary {
                    if let urlString = faviconDictionary["url"] as? String {
                        
                        // The favicon url (href in link tag) needs to be resolved to the url from the page
                        if let url = URL(string: urlString, relativeTo: self.webView.url) {
                            let sizesString = faviconDictionary["sizes"] as? String;
                            let sizeStrings = sizesString?.components(separatedBy: "x") ?? []
                            
                            if (sizeStrings.count == 2) {
                                let width = Int(sizeStrings[0])
                                let height = Int(sizeStrings[1])
                                faviconUrls.insert(FaviconUrl(url: url, width: width, height: height))
                            } else {
                                faviconUrls.insert(FaviconUrl(url: url, width: nil, height: nil))
                            }
                        }
                    }
                }
            }
        }
        
        // If no favicons were found, fallback to /favicon.ico
        // Note that some sites never replace the one that comes with the CMS. If you don't
        // use Javascript to parse the <link ...> tags, a site that works correctly in Chrome
        // could have a Drupal icon in your application
        if faviconUrls.count == 0 {
            if let webViewUrl = self.webView.url {
                let schemeAndHostUrl = webViewUrl.deletingPathExtension()
                let url = schemeAndHostUrl.appendingPathComponent("favicon.ico")
                faviconUrls.insert(FaviconUrl(url: url, width: nil, height: nil))
            }
        }
        
        if (faviconUrls != self.faviconUrls) {
            self.faviconUrls = faviconUrls
            self.delegate?.faviconChanged()
        }
        
        if error != nil {
            NSLog("Can not determine favicons: %@", error?.localizedDescription ?? "")
        }
    }
}

为了完整起见,这里是FaviconUrl类:

import Cocoa

class FaviconUrl: NSObject {

    public private(set) var url: URL
    public private(set) var width: Int?
    public private(set) var height: Int?
    
    init(url: URL, width: Int?, height: Int?) {
        self.url = url
        self.width = width
        self.height = height
    }
    
    public var area: Int? {
        get {
            if let width = self.width {
                if let height = self.height {
                    return width * height;
                }
            }
            
            return nil
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接