从 WKWebView 获取 favicon.co
Posted
技术标签:
【中文标题】从 WKWebView 获取 favicon.co【英文标题】:get favicon.co from WKWebView 【发布时间】:2016-02-05 10:58:40 【问题描述】:我正在为 OS X 和 ios 使用新的 wkWebView。为了将 webview 显示为图标,我需要显示的 URL 的图标。在旧的 webview 中,我可以使用以下功能:
var mainFrameIcon: NSImage! get
如何在 Swift 或 Objective-C 中使用 wkWebView 获取图像?
【问题讨论】:
【参考方案1】:新的 WKWebView 类似乎没有任何内置的公共网站图标,但有一种简单的方法可以检索它。由于网站将 favicon url 存储在 /favicon.ico,因此您只需从 web 视图中获取主机 url,将 /favicon.ico 添加到末尾并将 url 作为 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。【参考方案2】:就像这个帖子中的许多其他人所说的那样,找到一个网站图标不再是一件简单的事情。
因此,我开发了一个开源框架,可以为您完成繁重的工作。 https://github.com/will-lumley/FaviconFinder/
【讨论】:
【参考方案3】:不幸的是,获取网站图标不再是一个简单的属性。原因是网站可以为不同的分辨率声明多个网站图标。您(应用程序开发人员)需要根据您的需要选择合适的图标。
另一个复杂的问题是您(应用程序开发人员)需要在 WKWebView 对象中执行 javascript 才能从链接标签中获取网站图标!
(注意:依赖 /favicon.ico 容易出错。有些网站不会更新其 CMS 的 /favicon.ico,而仅通过链接标签进行设置。在这种情况下,具有正确图标的页面Chrome 可能会在您的自定义浏览器中显示 Drupal 图标。)
这里是 Javascript 来解析链接标签,然后是 Swift 来进一步读取结果。
// Based on code from https://***.com/questions/10282939/how-to-get-favicons-url-from-a-generic-webpage-in-javascript
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
【讨论】:
以上是关于从 WKWebView 获取 favicon.co的主要内容,如果未能解决你的问题,请参考以下文章