在C#中使用htmlagilitypack解析不同的HTML

时间:2014-12-30 14:53:34

标签: c# html-agility-pack

我需要一些关于如何使用htmlagilitypack和C#来概括HTML解析器的建议。我解析的网页包含员工信息。所有这些都有a)姓名,身份证,地址,电话 以下是可能出现或未出现的字段a)电子邮件b)传真c)工作时间d)skypeid

Employee 1
    <table>
    <tr><td nowrap>Name</td><td class="title"><b>Amy</b></td></tr><tr>
    <tr><td nowrap>ID</td><td class="title"><b>12345</b></td></tr><tr>
    <tr><td nowrap>Address</td><td class="title"><b>36 Main St, Baton Rouge, LA</b></td></tr><tr>
    <tr><td nowrap>Telephone</td><td class="title"><b>123-456-7890</b></td></tr><tr>
    <tr><td nowrap>Email</td><td class="title"><b>Amy@yahoo.com</b></td></tr><tr>
    <tr><td>skypeid</td><td class="title"><b>oilcompany</b></td></tr><tr>
    </table>

Employee 2
    <table>
    <tr><td nowrap>Name</td><td class="title"><b>Cathy</b></td></tr><tr>
    <tr><td nowrap>ID</td><td class="title"><b>99345</b></td></tr><tr>
    <tr><td nowrap>Address</td><td class="title"><b>36 Main St, Baton Rouge, LA</b></td></tr><tr>
    <tr><td nowrap>Telephone</td><td class="title"><b>123-456-7899</b></td></tr><tr>
    <tr><td nowrap>Working Hours</td><td class="title"><b>8 PM - 6 AM</b></td></tr><tr>
    <tr><td nowrap>fax</td><td class="title"><b>123-456-1111</b></td></tr><tr>
    </table>

代码:

    HtmlNodeCollection tdNoWraps = hdoc.DocumentNode.SelectNodes("//td[@nowrap]");
    HtmlNodeCollection tdNoWrapsclass = hdoc.DocumentNode.SelectNodes("//td[@class]");
    if(tdNoWraps != null)
    {
       if (tdNoWraps[0].InnerText.Trim().Contains("Name"))
                        dr["Name"] = tdNoWrapsclass[0].InnerText.Trim();

    ....
    }

如您所见,员工1与员工不同。如何编写通用解析器?并且'skypeid'也没有标签它只是。

由于 HR

2 个答案:

答案 0 :(得分:0)

所以每个员工都在一张桌子里? 表中的每一行都是员工的一个属性,第一列是属性名称,第二列是实际值。 我会把它放到一些Employee对象中,如:

class Employee{
  string Name {get; set;}
  string ID {get; set;}
  string Address {get; set;}
  string Telephone {get; set;}
  string Email {get; set;}
  string Fax {get; set;}
  string WorkingHours {get; set;}
  string SkypeId {get; set;}
}

您也可以使用try parse强力输入它,但现在只需使用下面的内容 某些边缘情况可能不会被覆盖,代码可能会中断,但您会想到我的想法。

HtmlNodeCollection tdNoWraps = hdoc.DocumentNode.SelectNodes("//td[@nowrap]");
HtmlNodeCollection tdNoWrapsclass = hdoc.DocumentNode.SelectNodes("//td[@class]");
var enumeratorNoWrapsClass = tdNoWrapsclass.GetEnumerator();
Employee employee = new Employee();

if(tdNoWraps != null)
{
 foreach (var element in tdNoWraps){
   if (element.InnerText.Trim().Contains("Name")){
                    employee.Name = enumeratorNoWrapsClass.Current.InnerText.Trim();
                }
   ....
  }
}

答案 1 :(得分:0)

从您的示例中,您似乎应该通过“td”(标签)和“td [@class]&#34;解析记录。 (值)因为skypeid不包含“nowarp”属性。

检查此样本:

员工对象

public class Employee
{
    public string ID { set; get; }
    public string Name { set; get; }
    public string Address { set; get; }
    public string Telephone { set; get; }
    public string Email { set; get; }
    public string WorkingHours { set; get; }
    public string Fax { set; get; }
    public string SkypeID { set; get; }
}

我只是建议循环遍历表,然后在每个循环中你需要遍历所有“td”元素(在表中),如果“td”没有定义“类”,它可以是作为标签处理,如果它有“类”,则为值(此时保存数据并转移到下一个属性)。

class Program
{
    static void Main(string[] args)
    {
        #region "HTML"

        string t = @"<table>
<tr><td nowrap>Name</td><td class=""title""><b>Amy</b></td></tr><tr>
<tr><td nowrap>ID</td><td class=""title""><b>12345</b></td></tr><tr>
<tr><td nowrap>Address</td><td class=""title""><b>36 Main St, Baton Rouge, LA</b></td></tr><tr>
<tr><td nowrap>Telephone</td><td class=""title""><b>123-456-7890</b></td></tr><tr>
<tr><td nowrap>Email</td><td class=""title""><b>Amy@yahoo.com</b></td></tr><tr>
<tr><td>skypeid</td><td class=""title""><b>oilcompany</b></td></tr><tr>
</table>

<table>
<tr><td nowrap>Name</td><td class=""title""><b>Cathy</b></td></tr><tr>
<tr><td nowrap>ID</td><td class=""title""><b>99345</b></td></tr><tr>
<tr><td nowrap>Address</td><td class=""title""><b>36 Main St, Baton Rouge, LA</b></td></tr><tr>
<tr><td nowrap>Telephone</td><td class=""title""><b>123-456-7899</b></td></tr><tr>
<tr><td nowrap>Working Hours</td><td class=""title""><b>8 PM - 6 AM</b></td></tr><tr>
<tr><td nowrap>fax</td><td class=""title""><b>123-456-1111</b></td></tr><tr>
</table> ";

        #endregion

        var doc = new HtmlDocument();
        doc.LoadHtml(t);


        var records = doc.DocumentNode.SelectNodes("//table");
        List<Employee> employees = new List<Employee>();
        foreach (var item in records)
        {
            var elem = item.Descendants().Where(m => m.Name == "td");
            var employee = new Employee();

            string elementName = "";
            foreach (var row in elem)
            {
                if (elementName == "")
                {
                    elementName = row.InnerText;
                }

                if (row.Attributes.Contains("class"))
                {
                    switch (elementName.Trim().ToLower())
                    {
                        case "name": employee.Name = row.InnerText.Trim();
                            break;
                        case "id": employee.ID = row.InnerText.Trim(); 
                            break;
                        case "address": employee.Address = row.InnerText.Trim();
                            break;
                        case "telephone": employee.Telephone = row.InnerText.Trim();
                            break;
                        case "email": employee.Email = row.InnerText.Trim();
                            break;
                        case "skypeid": employee.SkypeID = row.InnerText.Trim();
                            break;
                        case "working hours": employee.WorkingHours = row.InnerText.Trim();
                            break;
                        case "fax": employee.Fax = row.InnerText.Trim();
                            break; 
                    }

                    elementName = "";
                }
            }
            employees.Add(employee); 
        }

        foreach (var e in employees)
        {
            Console.WriteLine(e.Name);
        }

        Console.WriteLine("Press any key...");
        Console.ReadLine();
    } 
}