Android 使用JS注入获取网页视频链接
思路:
1、通过js注入获取整个网页html。
2、通过jsoup分析获取video播放器的数据源。
一、开启webviewjs功能,注入js回调
mWebView.addJavascriptInterface(new LocalAndroidObj(), "local_android_obj");// js 注入回调
二、通过jsoup 分析网页,使用方法类似jQuery语法。
private class LocalAndroidObj{
@JavascriptInterface
public void showSource(String msg){
// msg="<head>"+msg+"</head>";
Log.i("TAG", "showSource: html:"+msg);
Document parse = Jsoup.parse(msg);
Elements video_source = parse.select("video source");// 分析网页
if (video_source!=null){
for (Element element : video_source) {
String src = element.attr("src");//提取链接
Log.i("TAG", "showSource: src:"+src);
if (onParseListener!=null){
onParseListener.onFindUrl(src);
}
}
}
}
}
三、页面初始化后执行js注入回调。
@Override
public void onPageFinished(final WebView view, String url) {
super.onPageFinished(view, url);
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
// view.loadUrl("javascript:window.local_android_obj.showSource('<head>'+\" + \"document.getElementsByTagName('html')[0].innerHTML+'</head>');");
view.loadUrl("javascript:window.local_android_obj.showSource(document.getElementsByTagName('html')[0].outerHTML);");
// view.loadUrl("javascript:window.alert('jason');");
}
},100);
}
完整代码:
package com.jasonliyihang.ffmpegvideoplayer;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.UiAutomation;
import android.graphics.Bitmap;
import android.net.http.SslError;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.webkit.CookieManager;
import android.webkit.JavascriptInterface;
import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.util.Timer;
import java.util.TimerTask;
/**
* Created by Administrator on 2018/3/22.
*/
public class ParseWebUrlHelper {
private String mWebUrl;
private Activity mActivity;
private WebView mWebView;
private OnParseWebUrlListener onParseListener;
public static ParseWebUrlHelper getInstance() {
return new ParseWebUrlHelper();
}
public ParseWebUrlHelper init(Activity act, ViewGroup viewGroup) {
this.mActivity = act;
this.mWebView = new WebView(mActivity);
this.mWebView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
viewGroup.addView(this.mWebView);
initWebSettings();
return this;
}
public void free() {
if (mWebView != null) { //先从父容器中移除webview,然后再销毁webview
try {
ViewParent parent = mWebView.getParent();
if (parent != null) {
((ViewGroup) parent).removeView(mWebView);
}
mWebView.stopLoading(); // 退出时调用此方法,移除绑定的服务,否则某些特定系统会报错
mWebView.getSettings().setJavaScriptEnabled(false);
mWebView.clearHistory();
mWebView.clearCache(true);
mWebView.removeAllViews();
mWebView.destroy();
mWebView = null;
} catch (Exception e) {
e.printStackTrace();
}
}
}
@SuppressLint("SetJavaScriptEnabled")
private void initWebSettings() {
WebView mWebView = this.mWebView;
mWebView.clearFocus();
WebSettings mWebSettings = mWebView.getSettings();
mWebSettings.setJavaScriptEnabled(true);
mWebSettings.setDefaultTextEncodingName("utf-8");
mWebSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
mWebSettings.setDisplayZoomControls(false);
mWebSettings.setUseWideViewPort(true);
mWebSettings.setAllowFileAccess(true);
mWebSettings.setAllowContentAccess(true);
mWebSettings.setSupportZoom(true);
mWebSettings.setAllowContentAccess(true);
mWebSettings.setLoadWithOverviewMode(true);
mWebSettings.setBuiltInZoomControls(true);// 隐藏缩放按钮
mWebSettings.setUseWideViewPort(true);// 可任意比例缩放
mWebSettings.setLoadWithOverviewMode(true);// setUseWideViewPort方法设置webview推荐使用的窗口。setLoadWithOverviewMode方法是设置webview加载的页面的模式。
mWebSettings.setSaveFormData(true);// 保存表单数据
mWebSettings.setJavaScriptEnabled(true);
mWebSettings.setTextZoom(100);
mWebSettings.setDomStorageEnabled(true);
mWebSettings.setSupportMultipleWindows(true);// 新加//我就是没有这一行,死活不出来。MD,硬是没有人写这一句!
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mWebSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
mWebSettings.setMediaPlaybackRequiresUserGesture(true);
mWebSettings.setAllowFileAccessFromFileURLs(true);
mWebSettings.setAllowUniversalAccessFromFileURLs(true);
mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true);
mWebSettings.setLoadsImagesAutomatically(true);
mWebSettings.setAppCacheEnabled(true);
mWebSettings.setAppCachePath(mActivity.getCacheDir().getAbsolutePath());
mWebSettings.setDatabaseEnabled(true);
mWebSettings.setGeolocationDatabasePath(mActivity.getDir("database", 0).getPath());
mWebSettings.setGeolocationEnabled(true);
CookieManager instance = CookieManager.getInstance();
instance.setAcceptCookie(true);
if (Build.VERSION.SDK_INT >= 21) {
instance.setAcceptThirdPartyCookies(mWebView, true);
}
mWebView.setWebViewClient(new MyWebViewClient());
mWebView.setWebChromeClient(new GoogleWeb());
mWebView.addJavascriptInterface(new LocalAndroidObj(), "local_android_obj");// js 注入回调
enabledCookie(this.mWebView);//启用cookie
}
public ParseWebUrlHelper setLoadUrl(String url) {
this.mWebUrl = url;
return this;
}
public ParseWebUrlHelper startParse() {
mWebView.loadUrl(this.mWebUrl);
return this;
}
/*启用cookie*/
private void enabledCookie(WebView web) {
CookieManager instance = CookieManager.getInstance();
instance.setAcceptCookie(true);
if (Build.VERSION.SDK_INT >= 21) {
instance.setAcceptThirdPartyCookies(web, true);
}
}
public ParseWebUrlHelper setOnParseListener(OnParseWebUrlListener onParseListener) {
this.onParseListener = onParseListener;
return this;
}
private class GoogleWeb extends WebChromeClient {
}
private class LocalAndroidObj{
@JavascriptInterface
public void showSource(String msg){
// msg="<head>"+msg+"</head>";
Log.i("TAG", "showSource: html:"+msg);
Document parse = Jsoup.parse(msg);
Elements video_source = parse.select("video source");// 分析网页
if (video_source!=null){
for (Element element : video_source) {
String src = element.attr("src");//提取链接
Log.i("TAG", "showSource: src:"+src);
if (onParseListener!=null){
onParseListener.onFindUrl(src);
}
}
}
}
}
private class MyWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
if (request.getUrl().toString().startsWith("intent") || request.getUrl().toString().startsWith("youku")) {
return true;
} else {
return super.shouldOverrideUrlLoading(view, request);
}
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("intent") || url.startsWith("youku")) {
return true;
} else {
return super.shouldOverrideUrlLoading(view, url);
}
}
/*解决ssl证书问题*/
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
}
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
String url = request.getUrl().toString();
// onParseListener.onFindUrl(url);
}
return super.shouldInterceptRequest(view, request);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
startCount();//加载超时处理
}
@Override
public void onPageFinished(final WebView view, String url) {
super.onPageFinished(view, url);
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
// view.loadUrl("javascript:window.local_android_obj.showSource('<head>'+\" + \"document.getElementsByTagName('html')[0].innerHTML+'</head>');");
view.loadUrl("javascript:window.local_android_obj.showSource(document.getElementsByTagName('html')[0].outerHTML);");
// view.loadUrl("javascript:window.alert('jason');");
}
},100);
}
}
private void startCount() {
final Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
onParseListener.onError("解析视频超时,请检查网速或网络是否出现问题...");
timer.cancel();
timer.purge();
}
};
int timeOut = 20 * 1000;
timer.schedule(timerTask, timeOut, 1);
}
public interface OnParseWebUrlListener {
void onFindUrl(String url);
void onError(String errorMsg);
}
}
测试代码:
//初始化
parseWebUrlHelper = ParseWebUrlHelper.getInstance().init(this, frameLayout);
parseWebUrlHelper.setLoadUrl("https://www.w3school.com.cn/html5/html_5_video_dom.asp");
//解析网页中视频
parseWebUrlHelper.setOnParseListener(new ParseWebUrlHelper.OnParseWebUrlListener() {
@Override
public void onFindUrl(String url) {
Log.i("TAG", "onFindUrl: media url "+url);
}
@Override
public void onError(String errorMsg) {
}
});
parseWebUrlHelper.startParse();
如果对你有帮助请点赞 谢谢!!
参考:https://blog.csdn.net/a1021508536/article/details/52829243?utm_source=blogxgwz36