【问题标题】:How to detect AVplayer and get url of current video from WKWebView?如何检测 AVplayer 并从 WKWebView 获取当前视频的 url?
【发布时间】:2019-08-18 01:09:21
【问题描述】:

我正在使用下面的代码从 UIWebView 中提取 url:它工作正常,但是使用 WKWebView 的相同代码它不再工作了。谁能帮我?在 WKWebView 中播放的视频是 Inlineplacyback 而不是全屏。

我的代码是:

 NotificationCenter.default.addObserver(self, selector: #selector(self.playerItemBecameCurrent(_:)), name: NSNotification.Name("AVPlayerItemBecameCurrentNotification"), object: nil)

 @objc func playerItemBecameCurrent(_ sender : NSNotification){
    let playerItem: AVPlayerItem? = sender.object as? AVPlayerItem
    if playerItem == nil {
        print("player item nil")
        return
    }
    // Break down the AVPlayerItem to get to the path
    let asset = playerItem?.asset as? AVURLAsset
    let url: URL? = asset?.url
    let path = url?.absoluteString

    print(path!,"video url")
}

响应网址:

https://r2---sn-po4g5uxa-5hql.googlevideo.com/videoplayback?txp=5531432&sparams=clen%2Cdur%2Cei%2Cgir%2Cid%2Cinitcwndbps%2Cip%2Cipbits%2Citag%2Clmt%2Cmime%2Cmm%2Cmn%2Cms%2Cmv%2Cpcm2%2Cpl%2Cratebypass%2Crequiressl%2Csource%2Cexpire&ip=103.37.181.55&ratebypass=yes&id=o-AM9UWIaxopyYZX4gikGuswG8EMi3dhH_PPBMIqY5cbXj&expire=1554400796&c=MWEB&fvip=4&initcwndbps=481250&ipbits=0&mime=video%2Fmp4&dur=60.093&lmt=1554142002789460&key=yt6&mt=1554379078&itag=18&source=youtube&gir=yes&requiressl=yes&signature=6C68366FC249958BB8E95A5D88074FF8BCB99745.DA113E66DD0B46863BAE52DAA3CAB31FD141F0E5&clen=2708520&mm=31%2C29&mn=sn-po4g5uxa-5hql%2Csn-cvh7knek&ei=vPGlXPOWHIWD8QOO1KBo&ms=au%2Crdu&pcm2=no&pl=24&mv=m&cpn=I9d32bNmeq3kf0jn&cver=2.20190403&ptk=youtube_none&pltype=contentugc

它是 视频 URL 不是网页 URL 所以,请帮助我如何获得这个。 谢谢。

【问题讨论】:

  • 你能提供你正在使用的网址吗?
  • 不,我正在使用 WKWebView,所以当 webview 检测到正在播放视频时,我不想得到它。你能帮帮我吗?
  • @ViraniVivek 是一个能够在 WebView 中导航到不包含视频的不同页面的用户吗?还是只有视频链接?
  • @MCMatan 用户能够在 webview 中导航任何不同的页面,它是否包含视频,但是当转到包含视频的页面时,如果视频播放而不是获取当前视频播放的 url。

标签: ios swift avplayer wkwebview


【解决方案1】:

这是一种 hack,但我找到的唯一方法。

首先将自己设置为 WKWebView 导航代理:

self.webView?.navigationDelegate = self

现在监听所有导航变化,并保存请求的 url:

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        if let urlStr = navigationAction.request.url?.absoluteString {
            //Save presented URL
            //Full path can be accessed via self.webview.url
        }

        decisionHandler(.allow)
    }

现在您只需要知道新屏幕何时可见,并使用您保存的 URL(要知道新可见屏幕的视频 URL)。

您可以通过收听 UIWindowDidBecomeVisibleNotification 通知来做到这一点:

NotificationCenter.default.addObserver(self, selector: #selector(windowDidBecomeVisibleNotification(notif:)), name: NSNotification.Name("UIWindowDidBecomeVisibleNotification"), object: nil)

然后检查导航窗口是否不是您的窗口,这意味着确实打开了一个新屏幕:

@objc func windowDidBecomeVisibleNotification(notif: Notification) {
        if let isWindow = notif.object as? UIWindow {
            if (isWindow !== self.view.window) {
            print("New window did open, check what is the currect URL")
            }
        }
    }

【讨论】:

  • 这个方法在新窗口打开时调用,但是我怎样才能得到这个 avplayer 项目来获取视频 url?
  • 我不想这样做的应用程序功能itunes.apple.com/us/app/dmanager-browser-documents/… 应用程序正在以与我不希望的方式相同的方式进行。你能告诉我这个应用程序是如何获取视频网址的吗?当 avplayer 随时随地开始播放时,在 webview 中检测。
  • 请在你我之间建立一个团队,我会告诉你什么是不能做的。
  • 如果您只寻找视频 URL,我不确定为什么需要 avplayer。您可以通过我的解释获取视频 URL。你能解释一下你缺少什么
  • 首先我加载 youtube.com url,当我点击任何视频时,我想获取视频 url 而不是 webview 的当前 url。因此,您的通知仅在点击视频时触发一次,而不是第二次您的通知未触发。我想下载任何在 mywebview 中播放的视频
【解决方案2】:

从 WKNavigationDelegate 的 webView(_:decidePolicyFor:decisionHandler:) 方法中导航操作的请求属性中检索完整的 URL。

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    if let urlStr = navigationAction.request.url?.absoluteString {
        //urlStr is your URL
    }

    decisionHandler(.allow)
}

别忘了遵守协议

webView.navigationDelegate = self

【讨论】:

  • 我想获取实际的视频网址而不是网页网址itunes.apple.com/us/app/dmanager-browser-documents/… 请查看此应用程序并打开 youtube 并选择任何视频
  • @viraniVivek 我只为 youtube 视频做了同样的事情。我通过 youtubeURL 提供的视频 ID 存储特定视频。
【解决方案3】:

您可以尝试在WKWebView 中注入 JS,如下所示:https://paulofierro.com/blog/2015/10/12/listening-for-video-playback-within-a-wkwebview

【讨论】:

  • 他使用的方法不再有效
  • @MCMatan 是对的。这种方法不再起作用了。
【解决方案4】:

使用 Swift

您可以使用下面的代码从 webview 的 url 获取 html 内容

let docString = webView.stringByEvaluatingJavaScriptFromString("document.documentElement.outerHTML")

这种情况下你会得到整个html内容,

然后在html字符串中查找href链接

let regex = try! NSRegularExpression(pattern: "<a[^>]+href=\"(.*?)\"[^>]*>")
let range = NSMakeRange(0, docString.characters.count)
let matches = regex.matches(in: docString, range: range)
for match in matches {
    let htmlLessString = (docString as NSString).substring(with: match.rangeAt(1))
    print(htmlLessString)
}

使用

检查它是否是 youtube url

正则表达式:"@https?://(www.)?youtube.com/.[^\s.,"\']+@i"

实现这一目标的另一种方法

跳出框框思考!

您可以调用 api 来获取 url。使用 php、.net 等网络语言似乎很容易。

在 PHP 中获取网页内所有 url 的代码(使用任何适合您的语言)

$url="http://wwww.somewhere.com";
$data=file_get_contents($url);
$data = strip_tags($data,"<a>");
$d = preg_split("/<\/a>/",$data);
foreach ( $d as $k=>$u ){
    if( strpos($u, "<a href=") !== FALSE ){
        $u = preg_replace("/.*<a\s+href=\"/sm","",$u);
        $u = preg_replace("/\".*/","",$u);
        print $u."\n";
    }
}

是否为youtube url一一检查。

$sText =  "Check out my latest video here http://www.youtube.com/?123";
preg_match_all('@https?://(www\.)?youtube.com/.[^\s.,"\']+@i', $sText, $aMatches);
var_dump($aMatches);

如果您想检查示例应用程序是否使用相同的方法,请获取 Web 调试代理并对其进行挖掘

以上很多解释都取自其他网站。

我希望它能够满足您的需求! 编码愉快!

【讨论】:

  • 但我想检测来自任何网站的视频,这些网站在我的网页视图中打开,不仅适用于 youtube。对于演示,您可以在 iTunes 中查看应用程序,链接是 itunes.apple.com/us/app/dmanager-browser-documents/…
  • 那是php方面不在swift中?你能在 iTunes 中看到这个应用吗?
  • 您可以使用基本 url 对后端进行 api 调用,并获取过滤后的 youtube url 作为响应
  • 我只在 ios swift 或 obj C 中获取没有 PHP 的视频 url,即使它是我想要的无证 api。
  • 请给我任何相关的解决方案。
【解决方案5】:

在你的 ViewController 中试试这个,在 WKWebView 上添加一个 URL Observer:

override func loadView() {
    let webConfig = WKWebViewConfiguration()
    webView = WKWebView(frame: .zero, configuration: webConfig)
    webView.addObserver(self, forKeyPath: "URL", options: .new, context: nil)
    view = webView
}

覆盖observeValue获取url请求:

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == #keyPath(WKWebView.url) {
        let urlRequest:String = webView.url?.absoluteString ?? ""
        print(urlRequest)
    }
}

最后...取消观察者:

deinit { webView.removeObserver(self, forKeyPath: "URL") }

【讨论】:

  • 我已经尝试过了,但它给出的网页网址不是实际的视频网址
【解决方案6】:

在 WKWebView 中,我们需要添加 Inlineplacyback 的配置,在 WKWebViewConfiguration 中为 true。如果在 WKWebView 中设置了配置,它会自动进入全屏视图。

以下代码供参考:

class WebViewController: UIViewController {

  lazy var webView: WKWebView! = {
    
    let webView = WKWebView(frame: .zero, configuration: configuration)
    webView.translatesAutoresizingMaskIntoConstraints = false
    webView.uiDelegate = self
    webView.navigationDelegate = self
    let request = URLRequest(url: .init(string: "https://developer.apple.com/videos/play/wwdc2020/10188/")!)
    webView.load(request)
    return webView
    
  }()
  
  lazy var configuration: WKWebViewConfiguration! = {
    let configuration = WKWebViewConfiguration()
    configuration.allowsInlineMediaPlayback = true
    configuration.mediaTypesRequiringUserActionForPlayback = .audio
    configuration.allowsPictureInPictureMediaPlayback = true
    return configuration
  }()
  
  override func loadView() {
    super.loadView()
    
    self.view.backgroundColor = .white
    self.view.addSubview(self.webView)
    
    // Constraint
    
    NSLayoutConstraint.activate([
    
      self.webView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
      self.webView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor),
      self.webView.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor),
      self.webView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor),

    ])
    
  }

}

extension WebViewController: WKUIDelegate{
  
  
  
}

extension WebViewController: WKNavigationDelegate{
  
  
  func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse) async -> WKNavigationResponsePolicy {
    debugPrint("---------------------------- decidePolicyFor navigationResponse")
    return .allow
  }
    
  func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, preferences: WKWebpagePreferences, decisionHandler: @escaping (WKNavigationActionPolicy, WKWebpagePreferences) -> Void) {
    debugPrint("---------------------------- decidePolicyFor navigationAction")
    decisionHandler(.allow, .init())
  }
  
  
}

Click here查看示例输出视频

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多