【发布时间】:2020-12-05 18:21:41
【问题描述】:
Visual Studio 2017、Windows 10、.NET Framework 4.8、CefSharp WinForms 83.4.20、平台目标 x64
创建了新的非常简单的 CefSharp Windows Forms 应用程序。我无法获取网页的 html 源代码。我想我已经查看了 StackOverflow 上的每个 CefSharp 和异步同步问题 - 尝试了很多解决方案 - 我的头变得糊涂了。这是我看到的第一个问题 - 我有同样的问题。
Get HTML source code from CefSharp web browser
'浏览器.ViewSource();' 确实会弹出一个带有网页来源的记事本。但是当我尝试使用源代码获取字符串时 - 任务似乎永远不会运行。运行以获取网页源的任务说 ---> Status = WaitingForActivation ---> 并且永远不会返回源。
我已经尝试过异步到同步的转换——可能有十种不同的方式。没有工作。一个 StackOverflow 解决方案建议使用 Application.DoEvents() - 所以我什至尝试过。
希望有人有一些想法。这个浏览器似乎有很大的潜力 - 但我需要获取网页源 html。
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using CefSharp;
using CefSharp.WinForms;
using System.Diagnostics;
namespace Test1
{
public partial class Form1 : Form
{
public ChromiumWebBrowser browser;
public Form1()
{
InitializeComponent();
InitBrowser();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
browser.Dispose();
Cef.Shutdown();
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
public void InitBrowser()
{
Cef.Initialize(new CefSettings());
browser = new ChromiumWebBrowser("https://google.com/");
this.Controls.Add(browser);
browser.Dock = DockStyle.Fill;
browser.FrameLoadEnd += OnWebBrowserFrameLoadEnded;
}
void OnWebBrowserFrameLoadEnded(object sender, FrameLoadEndEventArgs e)
{
ChromiumWebBrowser BrowserSender = (ChromiumWebBrowser)sender;
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(() => { WebBrowserFrameLoadEnded(BrowserSender, e); }));
}
else
{
WebBrowserFrameLoadEnded(BrowserSender, e);
}
}
void WebBrowserFrameLoadEnded(ChromiumWebBrowser BrowserSender, FrameLoadEndEventArgs e)
{
string html1 = null;
Task<String> taskString1;
if (e.Frame.IsMain)
{
//browser.ViewSource();
taskString1 = Task.Run(() => GetBrowserSource(browser));
while (taskString1.Status != TaskStatus.RanToCompletion)
{
Application.DoEvents();
System.Threading.Thread.Sleep(100);
}
html1 = taskString1.Result;
Debug.WriteLine("");
}
}
async Task<string> GetBrowserSource(ChromiumWebBrowser Browser)
{
return await Browser.GetMainFrame().GetSourceAsync();
}
}
}
我的 app.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
</startup>
</configuration>
我的packages.config
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="cef.redist.x64" version="83.4.2" targetFramework="net452" />
<package id="cef.redist.x86" version="83.4.2" targetFramework="net452" />
<package id="CefSharp.Common" version="83.4.20" targetFramework="net452" />
<package id="CefSharp.WinForms" version="83.4.20" targetFramework="net452" />
</packages>
【问题讨论】:
-
该方法应该异步调用,不支持同步调用。
-
想补充一点背景资料来帮助别人。我是一名 .NET 程序员,从事屏幕抓取工作多年。过去我们可以使用 Windows 窗体浏览器控件来简单地导航到页面、读取 html 源代码并提取我们需要的内容。 HtmlAgility 是使用 html 源代码的巨大改进。我们甚至可以删除 Web Browser 控件,直接在 HtmlAgility 中加载 html。
-
但是随着网站中反屏幕抓取工具的增长,在 HtmlAgility 中直接加载 html 变得很困难 - 全部自动。我回到半自动的方式,使用Web Browser控件加载登录页面,手动登录,然后让HtmlAgility在登录后接管。最新的反屏幕抓取工具现在需要在浏览器中运行 cookie 和 javascript - 因此即使使用 Windows 窗体 Web 浏览器控件登录也很难完成。我在使用 CefSharp 时没有发现任何问题。
标签: c# asynchronous async-await cefsharp