在 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.