主要思想:通过后台WebView载入指定网页,再提取出WebView中的内容

关键代码:

var html = await webView.InvokeScriptAsync("eval", new string[] { "document.documentElement.outerHTML;" });

有一个很简单的思路,

订阅WebView NavigationCompleted事件,然后让Navigate到指定的网址,发生事件时执行这行代码

除此之外,这里还有一个异步的方法,用到了TaskCompletionSource这个东西

首先,创建一个TaskCompletionSource:

TaskCompletionSource<string> completionSource = new TaskCompletionSource<string>();

因为返回的东西是string(html),所以泛型T设置成string

然后使用lambda的形式订阅Navigation事件:

 webView.NavigationCompleted += async (sender, args) =>
{
if (args.Uri != uri)
return;
await Task.Delay();
var html = await sender.InvokeScriptAsync("eval", new string[] { "document.documentElement.outerHTML;" });
webView.NavigateToString("");
webView = null;
completionSource.SetResult(html);
};

Line5的延迟200ms,是为了Navigation完成之后再给页面里的其他一些元素(比如一些js脚本)一些加载的时间(讲道理订阅事件里也应该写一个的)

Line7的导航到空是为了防止WebView里的东西继续运行从而导致一些灵异事件(尤其是一些带视频的网页,咳咳)

Line9,给Task设置个Result,await就会结束

最后:

 return completionSource.Task;

封装成类:

    public class WebHelper
{
public class WebLoadedArgs:EventArgs
{
public bool Success { get; private set; }
public WebErrorStatus WebErrorStatus { get; private set; }
public string Html { get; private set; } public WebLoadedArgs(WebErrorStatus webErrorStatus)
{
WebErrorStatus = webErrorStatus;
Success = false;
} public WebLoadedArgs(string Html,WebErrorStatus webErrorStatus)
{
this.Html = Html;
WebErrorStatus = webErrorStatus;
Success = true;
}
} public string Url { get; private set; }
public event EventHandler<WebLoadedArgs> WebLoaded;
private WebView webView; public WebHelper(string Url)
{
this.Url = Url;
webView = new WebView(WebViewExecutionMode.SeparateThread);
webView.Navigate(new Uri(Url));
webView.NavigationCompleted += WebView_NavigationCompleted;
webView.NavigationFailed += WebView_NavigationFailed;
} private void WebView_NavigationFailed(object sender, WebViewNavigationFailedEventArgs e)
{
WebLoaded(this, new WebLoadedArgs(e.WebErrorStatus));
} private async void WebView_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
{ var html = await sender.InvokeScriptAsync("eval", new string[] { "document.documentElement.outerHTML;" });
webView = null;
WebLoaded(this, new WebLoadedArgs(html,args.WebErrorStatus));
} /// <summary>
/// 异步实现获取Web内容
/// </summary>
/// <param name="Url">网址</param>
/// <param name="TimeOut">超时时间</param>
/// <returns>Web的Html内容</returns>
public static Task<string> LoadWebAsync(string Url,int Timeout)
{
return LoadWebAsync(Url, "", Timeout);
} /// <summary>
/// 异步实现获取Web内容
/// </summary>
/// <param name="Url">网址</param>
/// <param name="Referer">Header[Referer],用以解决一些盗链效验</param>
/// <param name="TimeOut">超时时间</param>
/// <returns>Web的Html内容</returns>
public static Task<string> LoadWebAsync(string Url,string Referer, int TimeOut)
{ WebView webView = new WebView(WebViewExecutionMode.SeparateThread);
Uri uri = new Uri(Url);
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, uri);
requestMessage.Headers.Add("Referer", Referer);
webView.NavigateWithHttpRequestMessage(requestMessage); TaskCompletionSource<string> completionSource = new TaskCompletionSource<string>();
webView.NavigationCompleted += async (sender, args) =>
{
if (args.Uri != uri)
return;
await Task.Delay();
var html = await sender.InvokeScriptAsync("eval", new string[] { "document.documentElement.outerHTML;" });
webView.NavigateToString("");
webView = null;
completionSource.SetResult(html);
};
webView.NavigationFailed += (sender, args) =>
{
webView = null;
completionSource.SetException(new WebException("", (WebExceptionStatus)args.WebErrorStatus));
};
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(TimeOut);
timer.Tick += (sender, args) =>
{
timer = null;
webView.NavigateToString("");
webView = null;
completionSource.SetException(new TimeoutException());
};
timer.Start(); return completionSource.Task;
}
}

使用方法:

(事件订阅的方式)

        WebHelper webHelper = new WebHelper("http://www.baidu.com/");
webHelper.WebLoaded += WebHelper_WebLoaded; private void WebHelper_WebLoaded(object sender, WebHelper.WebLoadedArgs e)
{
if(e.Success)
{
var html = e.Html;
}
}

(异步的方式)

var html = await WebHelper.LoadWebAsync("http://www.baidu.com", );

UWP获取任意网页加载完成后的HTML的更多相关文章

  1. js判断图片加载完成后获取图片实际宽高

    通常,我们会用jq的.width()/.height()方法获取图片的宽度/高度或者用js的.offsetwidth/.offsetheight方法来获取图片的宽度/高度,但这些方法在我们通过样式设置 ...

  2. Web前端性能优化总结——如何提高网页加载速度

    一.提高网页加载速度的必要性 国际知名的一组来自Jupiter Research的数据显示:购物者在访问网站过程中的不满会导致销售损失和品牌受损,其中 77%的人将不再访问网站 ,62%的人不再从该网 ...

  3. 《转》如何让你的网页加载时间降低到 1s 内

    当初分析了定宽高值和定宽高比这两种常见的图片延迟加载场景,也介绍了他们的应对方案,还做了一点技术选型的工作. 经过一段时间的项目实践,在先前方案的基础上又做了很多深入的优化工作.最终将好奇心日报的网页 ...

  4. 使用WebView监控网页加载状况,PerformanceMonitor,WebViewClient生命周期

    原理:WebView加载Url完成后,注入js脚本,脚本代码使用W3C的PerformanceTimingAPI, 往js脚本传入一个Android对象(代码中为AndroidObject),在js脚 ...

  5. 如何让你的网页加载时间降低到 1s 内

    当初分析了定宽高值和定宽高比这两种常见的图片延迟加载场景,也介绍了他们的应对方案,还做了一点技术选型的工作. 经过一段时间的项目实践,在先前方案的基础上又做了很多深入的优化工作.最终将好奇心日报的网页 ...

  6. iOS WKWebView添加网页加载进度条(转)

    一.效果展示 WKWebProgressViewDemo.gif 二.主要步骤 1.添加UIProgressView属性 @property (nonatomic, strong) WKWebView ...

  7. 前端性能优化(四)——网页加载更快的N种方式

    网站前端的用户体验,决定了用户是否想要继续使用网站以及网站的其他功能,网站的用户体验佳,可留住更多的用户.除此之外,前端优化得好,还可以为企业节约成本.那么我们应该如何对我们前端的页面进行性能优化呢? ...

  8. 浅析用Base64编码的图片优化网页加载速度

    想必大家都知道网页加载的过程,从开始请求,到加载页面,开始解析和显示网页,遇到图片就再次向服务器发送请求,加载图片.如果图片很多的话,就会产生大量的http请求,从而影响页面的加载速度.所以现在有一种 ...

  9. Webbrowser控件判断网页加载完毕的简单方法 (转)

    摘自:http://blog.csdn.net/cometnet/article/details/5261192 一般情况下,当ReadyState属性变成READYSTATE_COMPLETE时,W ...

随机推荐

  1. Windows API 第19篇 FindFirstVolumeMountPoint FindNextVolumeMountPoint

    相关函数:HANDLE FindFirstVolumeMountPoint(                                                               ...

  2. scope标签笔记

      scope的几个属性详解: 1.compile:默认值 他表示被依赖项目需要参与当前项目的编译,还有后续的测试,运行周期也参与其中,是一个比较强的依赖.打包的时候通常需要包含进去. 2.test: ...

  3. CF1140F - Extending Set of Points

    题意:对于点集S,定义函数F(S)为对S不断扩展到不能扩展时S的点数.一次扩展定义为如果有一个平行于坐标轴的矩形的三个点在S中,则第四个点加入S. 动态在S中加点删点,每次操作完后求F(S)的值. 解 ...

  4. HZOI20190810 T1

    A:blue(青蛙乱跳) 好像很多人都是用的队列?甚至还有用set 然而...博主太蒻了,只能找一个sb的规律 我们来手模一个样例: 10 9 16 30 2 4 6 9 11 15 18 19 25 ...

  5. thinkcmf报错:fileowner(): stat failed for /sys

    thinkcmf转移到linux云服务器后,后台更新缓存页面报错,错误信息fileowner(): stat failed for /sys 临时解决办法:修改common.php cmf_clear ...

  6. 谈谈数据库sql编写

    本文主要给初学者关于关系数库的一个浮光掠影式的介绍,如果想深入理解,必须对于下文提到的每个内容单独深入学习! it-information technology的简称,中文是信息机技术,信息其实就是数 ...

  7. Linux Shell脚本经典案例

    开头加解释器:#!/bin/bash    语法缩进,使用四个空格:多加注释说明.    命名建议规则:变量名大写.局部变量小写,函数名小写,名字体现出实际作用.    默认变量是全局的,在函数中变量 ...

  8. JS的闭包问题

    1.什么是“闭包” 是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 2.闭包的应用场景 (1)保护变量的安全实现JS私有属性和私有方法 (2)在 ...

  9. day18 8.jdbc中设置事务隔离级别

    设置数据库事务隔离级别特殊需求才有,后面很少用.因为数据库本身是事务隔离级别的,mysql的事务隔离级别是Repeatable read,可以解决脏读和不可重复读.不用设置,人家数据库是有事务隔离级别 ...

  10. A20地址线科普【转载】

    1981 年8 月,IBM 公司最初推出的个人计算机IBM PC 使用的CPU 是Intel 8088.在该微机中地址线只有20 根(A0 – A19).在当时内存RAM 只有几百KB 或不到1MB ...