在C#中,使用System.Windows.Forms.HtmlDocument类(或允许DOM解析的另一个类),是否有可能等到网页在检索HTML之前完成对HTML的javascript操作?某些网站通过javascript向页面添加innerhtml,但是当我解析HtmlDocument的HtmlElements时,这些更改不会显示。
一种可能性是在一秒钟之后更新页面的HtmlDocument。有人知道怎么做吗?
答案 0 :(得分:2)
有人通过张贴我认为不正确的答案来重振这个问题。所以,我想解决这个问题。
非确定性地,可以近距离查看页面是否已完成其AJAX内容。但是,它完全取决于该特定页面的逻辑:某些页面永远是动态的。
要解决此问题,可以首先处理DocumentCompleted
事件,然后异步轮询WebBrowser.IsBusy
属性并监视页面的当前HTML快照以进行更改,如下所示。
完整的样本可以是found here。
// get the root element
var documentElement = this.webBrowser.Document.GetElementsByTagName("html")[0];
// poll the current HTML for changes asynchronosly
var html = documentElement.OuterHtml;
while (true)
{
// wait asynchronously, this will throw if cancellation requested
await Task.Delay(500, token);
// continue polling if the WebBrowser is still busy
if (this.webBrowser.IsBusy)
continue;
var htmlNow = documentElement.OuterHtml;
if (html == htmlNow)
break; // no changes detected, end the poll loop
html = htmlNow;
}
答案 1 :(得分:1)
一般情况下,aswer是“不” - 除非页面上的脚本以某种方式通知您的代码,否则您只需等待一段时间并抓取HTML。在文档就绪通知后等待一秒钟将覆盖大多数站点(即jQuery的$(code)
个案例)。
答案 2 :(得分:0)
您需要为应用程序提供一秒钟来处理Java。简单地暂停当前线程也会延迟java处理,因此你的文档仍然会过时。
WebBrowserDocumentCompletedEventArgs cachedLoadArgs;
private void TimerDone(object sender, EventArgs e)
{
((Timer)sender).Stop();
respondToPageLoaded(cachedLoadArgs);
}
void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
cachedLoadArgs = e;
System.Windows.Forms.Timer timer = new Timer();
int interval = 1000;
timer.Interval = interval;
timer.Tick += new EventHandler(TimerDone);
timer.Start();
}
答案 3 :(得分:-1)
使用'WebBrowser.Navigated'事件怎么样?
答案 4 :(得分:-1)
我用WEbBrowser制作了一下我的课程:
public class MYCLASSProduct: IProduct
{
public string Name { get; set; }
public double Price { get; set; }
public string Url { get; set; }
private WebBrowser _WebBrowser;
private AutoResetEvent _lock;
public void Load(string url)
{
_lock = new AutoResetEvent(false);
this.Url = url;
browserInitializeBecauseJavascriptLoadThePage();
}
private void browserInitializeBecauseJavascriptLoadThePage()
{
_WebBrowser = new WebBrowser();
_WebBrowser.DocumentCompleted += webBrowser_DocumentCompleted;
_WebBrowser.Dock = DockStyle.Fill;
_WebBrowser.Name = "webBrowser";
_WebBrowser.ScrollBarsEnabled = false;
_WebBrowser.TabIndex = 0;
_WebBrowser.Navigate(Url);
Form form = new Form();
form.Hide();
form.Controls.Add(_WebBrowser);
Application.Run(form);
_lock.WaitOne();
}
private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
HtmlAgilityPack.HtmlDocument hDocument = new HtmlAgilityPack.HtmlDocument();
hDocument.LoadHtml(_WebBrowser.Document.Body.OuterHtml);
this.Price = Convert.ToDouble(hDocument.DocumentNode.SelectNodes("//td[@class='ask']").FirstOrDefault().InnerText.Trim());
_WebBrowser.FindForm().Close();
_lock.Set();
}
如果您尝试在控制台应用程序中执行此操作,则需要将此标记放在main上面,因为Windows需要与COM组件通信:
[STAThread]
static void Main(string[] args)
我不喜欢这个解决方案,但我认为没有人更好!