C# 如何使用C在本地自动获取联机HTML表#

C# 如何使用C在本地自动获取联机HTML表#,c#,html,asp.net-mvc,excel,C#,Html,Asp.net Mvc,Excel,好吧,简短一点: 我有一些不同的网站,其中的表格包含我想查询的“本地”信息 我一直在寻找可能性,我自己也有一些想法 在Excel中,我找到了一个可以导航到网页并从表中复制数据的函数。问题是这种情况只发生一次。表格中的数据每周都会更新,所以我需要Excel在每次打开程序时自动更新 我可以使用爬虫,但是我必须为每个表编写不同的解决方案,并找到保存它的方法 我有一个MySQL数据库,它包含了我程序中需要的许多信息,所以如果有任何解决方案需要一个完全可以接受的数据库 关于我的程序:将用C#编写,首先作为

好吧,简短一点:

我有一些不同的网站,其中的表格包含我想查询的“本地”信息

我一直在寻找可能性,我自己也有一些想法

  • 在Excel中,我找到了一个可以导航到网页并从表中复制数据的函数。问题是这种情况只发生一次。表格中的数据每周都会更新,所以我需要Excel在每次打开程序时自动更新

  • 我可以使用爬虫,但是我必须为每个表编写不同的解决方案,并找到保存它的方法

  • 我有一个MySQL数据库,它包含了我程序中需要的许多信息,所以如果有任何解决方案需要一个完全可以接受的数据库

    关于我的程序:将用C#编写,首先作为本地程序,然后作为MVC项目。这两个项目的建议都是非常受欢迎的,如果您需要更多信息,请发表评论,我将尝试更多地描述它。:)

    编辑!1

    很抱歉,我从一开始就没有告诉你我在谈论哪些表格,但是当我开始这个问题时,我仍然需要找到所有的表格。然而,现在,我已经拿出其中的一些来向你们展示我必须使用的不同类型的表。关于这个项目,它应该告诉你,我计划制作的程序只供私人使用,不出售。我不知道在公共网站上爬行的规则,所以我把它保密


    正如你所看到的,有很多足球数据以非常不同的方式显示,因此我需要知道哪种方式最适合我收集数据,因为我相信用这些知识设计医学数据库更容易。

    如果我只是阅读网页信息,我觉得这非常有用。它使得使用LINQ查找具有标识信息的特定标记,然后轻松导航子标记变得非常容易。因此,您可以找到标记,轻松查找并捕获文本属性以查找单元格的内容。

    您可以使用,他们有一个API,您可以从.NET使用,您可以使用他们的设计器构建模板以提取所需的数据,这非常容易使用,我的公司已经使用它从网站上获取评论,即使是通过分页和搜索。

    安德斯,Excel有一种内置的方法来获取数据,你必须这样做一次。下次您只需刷新查询即可。请查看此链接

    跟进

    试着看看这个页面:soccernet.espn.go.com/stats/_/league/eng.1/…有3个表,但excel似乎没有检测到它们:(–Anders Gerner 7分钟前

    在这个特定的网站中,如果您查看源代码,您将看到该表没有ID。所有三个表都具有相同的类“tablehead”。如果您愿意,在工作簿打开事件中,循环遍历所有表并提取数据。由于所有三个表都具有相同的类,因此您的工作变得更加轻松

    或者,您也可以这样做

    在Excel中,单击文件|打开,然后在对话框中直接键入下面提到的URL。您会注意到Excel将数据整齐地堆叠起来:)


    实际上,您可以编写一个小宏/代码,打开临时工作簿,然后打开URL,然后将临时工作簿中的表提取到工作簿中。我的估计是,在良好的internet连接上,完成整个过程不应超过15秒

    我的方法是使用工具为包含表数据的每个URL生成RSS提要,然后在UI中显示数据(无论是WPF、WinForms还是asp.net)。通过这种方式,当您找到/获取一个新网站以从中提取数据时,您可以轻松设置其他“频道”,您的工作将是将新网站标准化为您的标准rss提要格式(可在其中一个工具中配置),您甚至可以配置UI以根据配置设置提取其他提要,因此,添加新站点时无需重新编译

    您可以决定将提要数据存储在数据库中,或者只是实时显示,并自动实现定期缓存/刷新数据。我认为这种方法的基本前提是将每个站点的各种表格格式标准化为一种通用格式(rss或其他格式),然后只担心在应用程序中使用一种标准格式。这种方法可以在以通用格式显示数据的类库中设置,然后该类库可以被C#app和web应用程序使用

    编辑:这里有一个链接,介绍了一些可以用于从任何网站创建RSS提要的工具的相关信息:

    您可以使用Selenium(用于自动web测试)。这是一个非常有用的工具。它的API允许您通过XPath、CSS或DOM搜索特定的表

    您可以通过多种不同语言的“远程控制”来驱动Selenium。见:

    参见C#的示例:

    有关一些示例,请参见StackoverFlow:

    以下是一些使用HtmlAgilityPack的示例代码:

    using System;
    using System.Collections.Generic;
    using System.Web;
    using System.Xml.XPath;
    
    using HtmlAgilityPack;
    
    namespace TableRipper
    {
        class Program
        {
            static List<string> SerializeColumnSet(XPathNodeIterator columnSet)
            {
                List<string> serialized = new List<string>();
    
                while (columnSet.MoveNext())
                {
                    string value = HttpUtility.HtmlDecode(columnSet.Current.Value.ToString().Trim());
    
                    if (value.Contains(",") || value.Contains("\""))
                    {
                        value = string.Concat('"', value.Replace("\"", "\"\""), '"');
                    }
    
                    serialized.Add(value);
                }
    
                return serialized;
            }
    
            static List<List<string>> RipTable(string url, string xpath, bool includeHeaders = true)
            {
                HtmlWeb web = new HtmlWeb();
                HtmlDocument document = web.Load(url);
                XPathNavigator navigator = document.CreateNavigator();
                XPathNodeIterator tableElementSet = navigator.Select(xpath);
                List<List<string>> table = new List<List<string>>();
    
                if (tableElementSet.MoveNext())
                {
                    XPathNavigator tableElement = tableElementSet.Current;
                    XPathNavigator tableBodyElement = tableElement.SelectSingleNode("tbody") ?? tableElement;
                    XPathNodeIterator tableRowSet = tableBodyElement.Select("tr");
                    bool hasRows = tableRowSet.MoveNext();
    
                    if (hasRows)
                    {
                        if (includeHeaders)
                        {
                            XPathNavigator tableHeadElement = tableElement.SelectSingleNode("thead");
                            XPathNodeIterator tableHeadColumnSet = null;
    
                            if (tableHeadElement != null)
                            {
                                tableHeadColumnSet = tableHeadElement.Select("tr/th");
                            }
                            else if ((tableHeadColumnSet = tableRowSet.Current.Select("th")).Count > 0)
                            {
                                hasRows = tableRowSet.MoveNext();
                            }
    
                            if (tableHeadColumnSet != null)
                            {
                                table.Add(SerializeColumnSet(tableHeadColumnSet));
                            }
                        }
    
                        if (hasRows)
                        {
                            do
                            {
                                table.Add(SerializeColumnSet(tableRowSet.Current.Select("td")));
                            }
                            while (tableRowSet.MoveNext());
                        }
                    }
                }
    
                return table;
            }
    
            static void Main(string[] args)
            {
                foreach (List<string> row in RipTable(args[0], args[1]))
                {
                    Console.WriteLine(string.Join(",", row));
                }
            }
        }
    }
    
    使用系统;
    使用System.Collections.Generic;
    使用System.Web;
    使用System.Xml.XPath;
    使用HtmlAgilityPack;
    名称空间表格裂土器
    {
    班级计划
    {
    静态列表序列化列集(XPathNodeIterator列集)
    {
    列表序列化=新列表();
    while(columnSet.MoveNext())
    {
    string value=HttpUtility.HtmlDecode(columnSet.Current.value.ToString().Trim());
    if(value.Contains(“,”)| value.Contains(“\”))
    {
    value=string.Concat(“”,value.Replace(“\”,“\”),“\”);
    }
    序列化。添加(值);
    }
    返回序列化;