从CefSharp网页浏览器获取HTML源代码

22
我正在使用aCefSharp.Wpf.ChromiumWebBrowser(版本47.0.3.0)来加载一个网页。在页面加载完成后的某个时刻,我想获取该网页的源代码。
我已经调用了:
wb.GetBrowser().MainFrame.GetSourceAsync()

然而,它似乎没有返回所有源代码(我相信这是因为有子框架)。

如果我调用:

wb.GetBrowser().MainFrame.ViewSource() 

我可以看到它列出了所有的源代码(包括内部框架)。

我想要得到与ViewSource()相同的结果。请有人指点我正确的方向吗?

更新-添加代码示例

注意:Web浏览器指向的地址仅适用于10/03/2016及之前的日期。之后,它可能显示不同的数据,这不是我想查看的内容。

在frmSelection.xaml文件中

<cefSharp:ChromiumWebBrowser Name="wb" Grid.Column="1" Grid.Row="0" />
在 frmSelection.xaml.cs 文件中。
public partial class frmSelection : UserControl
{
    private System.Windows.Threading.DispatcherTimer wbTimer = new System.Windows.Threading.DispatcherTimer();

    public frmSelection()
    {

         InitializeComponent();

         // This timer will start when a web page has been loaded.
         // It will wait 4 seconds and then call wbTimer_Tick which 
         // will then see if data can be extracted from the web page.
         wbTimer.Interval = new TimeSpan(0, 0, 4);
         wbTimer.Tick += new EventHandler(wbTimer_Tick);

         wb.Address = "http://www.racingpost.com/horses2/cards/card.sd?race_id=644222&r_date=2016-03-10#raceTabs=sc_";

         wb.FrameLoadEnd += new EventHandler<CefSharp.FrameLoadEndEventArgs>(wb_FrameLoadEnd);

    }

        void wb_FrameLoadEnd(object sender, CefSharp.FrameLoadEndEventArgs e)
        {
            if (wbTimer.IsEnabled)
                wbTimer.Stop();

            wbTimer.Start();
        }

    void wbTimer_Tick(object sender, EventArgs e)
    {
        wbTimer.Stop();
        string html = GetHTMLFromWebBrowser();
    }

    private string GetHTMLFromWebBrowser()
    {
         // call the ViewSource method which will open up notepad and display the html.
         // this is just so I can compare it to the html returned in GetSourceAsync()
         // This is displaying all the html code (including child frames)
            wb.GetBrowser().MainFrame.ViewSource();

         // Get the html source code from the main Frame.
            // This is displaying only code in the main frame and not any child frames of it.
            Task<String> taskHtml = wb.GetBrowser().MainFrame.GetSourceAsync();

            string response = taskHtml.Result;
     return response;
  }

}

你能分享更多的代码吗?我无法重现你的问题,使用GetSourceAsyncViewSource获得相同的文本。我已经尝试了Address设置为http://stackoverflow.com(它有两个框架,一个是iframe和一个主框架)。 - Szabolcs Dézsi
谢谢查阅。我已经在原帖中添加了示例源代码。 - Scott
3个回答

32

我不太理解这个DispatcherTimer解决方案。我会这样做:

public frmSelection()
{
    InitializeComponent();

    wb.FrameLoadEnd += WebBrowserFrameLoadEnded;
    wb.Address = "http://www.racingpost.com/horses2/cards/card.sd?race_id=644222&r_date=2016-03-10#raceTabs=sc_";
}

private void WebBrowserFrameLoadEnded(object sender, FrameLoadEndEventArgs e)
{
    if (e.Frame.IsMain)
    {
        wb.ViewSource();
        wb.GetSourceAsync().ContinueWith(taskHtml =>
        {
            var html = taskHtml.Result;
        });
    }
}

我对ViewSource的输出和html变量中的文本进行了比较,它们是相同的,所以我无法在这里复现您的问题。

尽管如此,我注意到主框架加载得相当晚,因此您必须等待相当长的时间才能弹出记事本并显示源代码。


1
感谢您对我的代码提供反馈,我已经更新了它以反映您的示例。自从发布示例以来,我已在另一台计算机上运行了该代码,并获得了与您相同的结果(两者都返回完整的源代码)。我只能得出结论,我的计算机出现了一些奇怪的问题,我会考虑进行格式化。 - Scott

2

我遇到了同样的问题,尝试点击位于框架中而不是主框架上的项目。使用你答案中的示例,我编写了以下扩展方法:

        public static IFrame GetFrame(this ChromiumWebBrowser browser, string FrameName)
    {
        IFrame frame = null;

        var identifiers = browser.GetBrowser().GetFrameIdentifiers();

        foreach (var i in identifiers)
        {
            frame = browser.GetBrowser().GetFrame(i);
            if (frame.Name == FrameName)
                return frame;
        }

        return null;
    }

如果您的表单中包含此方法所在的模块的“使用”,则可以执行以下操作:
var frame = browser.GetFrame("nameofframe");
        if (frame != null)
        {
            string HTML = await frame.GetSourceAsync();
        }

当然,在使用此功能之前,您需要确保页面加载完成,但我计划经常使用它。希望它能有所帮助!
Jim

0
private void button1_Click(object sender, EventArgs e)
{
    Task<String> taskHtml = CW.GetBrowser().MainFrame.GetSourceAsync();
    textBox1.Text = taskHtml.Result;
}

虽然这段代码可能解决了问题,但是如果能够附上解释这段代码是如何解决问题的,将会极大地提升你的回答质量,并且可能会得到更多的赞同。请记住,你的回答是为了未来的读者而写的,而不仅仅是回答当前提问的人。请[编辑]你的回答,添加解释,并指明适用的限制和假设。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接