在 Windows.Form 中从 div 抓取数据
Scrape data from div in Windows.Form
我是 C# 编程新手。我正在尝试从 div 抓取数据(我想在 Forms 应用程序中显示网页的温度)。
这是我的代码:
private void btnOnet_Click(object sender, EventArgs e)
{
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
HtmlWeb web = new HtmlWeb();
doc = web.Load("https://pogoda.onet.pl/");
var temperatura = doc.DocumentNode.SelectSingleNode("/html/body/div[1]/div[3]/div/section/div/div[1]/div[2]/div[1]/div[1]/div[2]/div[1]/div[1]/div[1]");
onet.Text = temperatura.InnerText;
}
这是例外情况:
System.NullReferenceException:
temperatura was null.
你可以使用这个:
public static bool TryGetTemperature(HtmlAgilityPack.HtmlDocument doc, out int temperature)
{
temperature = 0;
var temp = doc.DocumentNode.SelectSingleNode(
"//div[contains(@class, 'temperature')]/div[contains(@class, 'temp')]");
if (temp == null)
{
return false;
}
var text = temp.InnerText.EndsWith("°") ?
temp.InnerText.Substring(0, temp.InnerText.Length - 5) :
temp.InnerText;
return int.TryParse(text, out temperature);
}
如果您使用 XPath,您可以 select 更精确地设置目标。对于您的查询,HTML 结构稍作更改,您的应用程序将失败。几点:
- //是在文档的任何地方搜索
- 您搜索任何包含 class“温度”的 div,并且在该节点内:
- 你用“temp”搜索 div child class
- 如果你得到那个节点(!= null),你尝试转换度数(删除之前的'°')
并检查:
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
HtmlWeb web = new HtmlWeb();
doc = web.Load("https://pogoda.onet.pl/");
if (TryGetTemperature(doc, out int temperature))
{
onet.Text = temperature.ToString();
}
更新
我对 TryGetTemperature 进行了一些更新,因为度数是经过编码的。主要问题是HTML。当您请求源代码时,您会得到一些浏览器稍后动态更新的 HTML。所以你得到的 HTML 对你无效。它不包含温度。
所以,我看到两个备选方案:
- 您可以使用浏览器控件(在公共控件 -> WebBrowser 中,在带有按钮、标签的表单工具中...),插入您的表单并导航到页面。这并不难,但你需要学习一些东西:等待页面下载的事件,然后从控件中获取源代码。另外,我想你会想要隐藏浏览器控件。请小心,如果您隐藏,有时浏览器将无法正常工作。在这种情况下,您可以在桌面外使用可见的表单并管理激活事件以避免激活此 window。此外,隐藏任务 Window (Alt+Tab)。事情以这种方式变得更难,但有时是唯一的方式。
- 简单的方法是搜索您想要的位置(例如:Madryt)并在 DevTools 中查看已完成的请求(例如:https://pogoda.onet.pl/prognoza-pogody/madryt-396099)。使用这个 Url 你会得到一个有效的 HTML.
我是 C# 编程新手。我正在尝试从 div 抓取数据(我想在 Forms 应用程序中显示网页的温度)。 这是我的代码:
private void btnOnet_Click(object sender, EventArgs e)
{
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
HtmlWeb web = new HtmlWeb();
doc = web.Load("https://pogoda.onet.pl/");
var temperatura = doc.DocumentNode.SelectSingleNode("/html/body/div[1]/div[3]/div/section/div/div[1]/div[2]/div[1]/div[1]/div[2]/div[1]/div[1]/div[1]");
onet.Text = temperatura.InnerText;
}
这是例外情况:
System.NullReferenceException: temperatura was null.
你可以使用这个:
public static bool TryGetTemperature(HtmlAgilityPack.HtmlDocument doc, out int temperature)
{
temperature = 0;
var temp = doc.DocumentNode.SelectSingleNode(
"//div[contains(@class, 'temperature')]/div[contains(@class, 'temp')]");
if (temp == null)
{
return false;
}
var text = temp.InnerText.EndsWith("°") ?
temp.InnerText.Substring(0, temp.InnerText.Length - 5) :
temp.InnerText;
return int.TryParse(text, out temperature);
}
如果您使用 XPath,您可以 select 更精确地设置目标。对于您的查询,HTML 结构稍作更改,您的应用程序将失败。几点:
- //是在文档的任何地方搜索
- 您搜索任何包含 class“温度”的 div,并且在该节点内:
- 你用“temp”搜索 div child class
- 如果你得到那个节点(!= null),你尝试转换度数(删除之前的'°')
并检查:
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
HtmlWeb web = new HtmlWeb();
doc = web.Load("https://pogoda.onet.pl/");
if (TryGetTemperature(doc, out int temperature))
{
onet.Text = temperature.ToString();
}
更新
我对 TryGetTemperature 进行了一些更新,因为度数是经过编码的。主要问题是HTML。当您请求源代码时,您会得到一些浏览器稍后动态更新的 HTML。所以你得到的 HTML 对你无效。它不包含温度。
所以,我看到两个备选方案:
- 您可以使用浏览器控件(在公共控件 -> WebBrowser 中,在带有按钮、标签的表单工具中...),插入您的表单并导航到页面。这并不难,但你需要学习一些东西:等待页面下载的事件,然后从控件中获取源代码。另外,我想你会想要隐藏浏览器控件。请小心,如果您隐藏,有时浏览器将无法正常工作。在这种情况下,您可以在桌面外使用可见的表单并管理激活事件以避免激活此 window。此外,隐藏任务 Window (Alt+Tab)。事情以这种方式变得更难,但有时是唯一的方式。
- 简单的方法是搜索您想要的位置(例如:Madryt)并在 DevTools 中查看已完成的请求(例如:https://pogoda.onet.pl/prognoza-pogody/madryt-396099)。使用这个 Url 你会得到一个有效的 HTML.