我在Yahoo新闻上使用WebBrowser控件进行网页抓取。我需要使用WebBrowser而不是HtmlAgilityPack来适应JavaScript等。
应用类型: WinForm
.NET Framework: 4.5.1
VS: 2013年终极版
操作系统: Windows 7专业版64位
我能够抓取所需的文本,但是当抓取完成时,我无法将应用程序的控制权返回给调用函数或任何其他函数。我也无法验证抓取是否完整。
我需要 1.确认所有页面加载和抓取都已完成 2.对结果列表执行操作,例如按字母顺序排列 3.对数据执行某些操作,例如在文本框中显示文本内容或将其写入SQL。
我为WebBrowser声明了新的类变量,以及一个URL列表和一个包含新闻文章列表的属性的对象。
public partial class Form1 : Form
{
public WebBrowser w = new WebBrowser(); //WebBrowser
public List<String> lststrURLs = new List<string>(); //URLs
public ProcessYahooNews pyn = new ProcessYahooNews(); //Contains articles
...
lststrURLs.Add("http://news.yahoo.com/sample01");
lststrURLs.Add("http://news.yahoo.com/sample02");
lststrURLs.Add("http://news.yahoo.com/sample03");
按下一个按钮,其处理程序正在调用函数,调用此代码。
w.Navigate(strBaseURL + lststrTickers[0]); //invokes w_Loaded
foreach (YahooNewArticle article in pyn.articles)
{
textBox1.Text += article.strHeadline + "\r\n";
textBox1.Text += article.strByline + "\r\n";
textBox1.Text += article.strContent + "\r\n";
textBox1.Text += article.dtDate.ToString("yyyymmdd") + "\r\n\r\n";
}
我遇到的第一个问题是程序控件似乎跳过w.Navigate
并直接传递到foreach
块,由于尚未填充articles
,因此该块无效。只有这时w.Navigate executed.
如果我能让foreach
块等到w.Navigate
完成其工作后,那么我的许多问题都将得到解决。如果没有,w.Navigate将完成它的工作,但后来我需要控制权传递给调用函数。
我已经进行了部分解决方案。
w.Navigate将页面加载到WebBrowser中。加载完成后,事件w.DocumentCompleted
将会触发。我正在使用w_Loaded
处理事件,该事件使用带逻辑的类来执行Web抓取。
// Sets up the class
pyn.ProcessYahooNews_Setup(w, e);
// Perform the scraping
pyn.ProcessLoad();
抓取的结果是填充pyn.articles
。仅在标准时加载下一页,例如pyn.articles.Count > 0
。
if (pyn.articles.Count > 0)
{
//Navigate to the next page
i++;
w.Navigate(lststrURLs[i]);
}
抓取更多网页,articles.Count
增长。但是,我无法确定是否已完成抓取 - 不会有更多页面加载导致更多文章。
假设我确信抓取已完成,我需要使articles
可用于进一步处理,例如将其排序为列表,删除某些元素,并将其文本内容显示到TextBox。
这让我回到过早调用的foreach
块。现在,我需要它,但我无法将articles
放入foreach
。我不认为我可以从w_Loaded调用其他函数到我的处理,因为它会被调用每个页面加载,我需要在所有页面加载后调用该函数一次。
在我看来,某些线程架构可能有所帮助,但我可以使用一些帮助来弄清楚架构的外观。