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

本文关键字:HTML htmlagilitypack | 更新日期: 2023-09-27 18:35:38

我需要一些关于如何使用 htmlagilitypack 和 C# 推广 HTML 解析器的建议。我解析的网页包含员工信息。他们都有a)姓名,ID,地址,电话以下是可能出现也可能不会出现的字段 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"也没有标签,它只是.

谢谢人力资源

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

从您的示例中,您似乎应该通过"td"(标签)和"td[@class]"(值)来分析记录,因为 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();
    } 
}

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

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();
                }
   ....
  }
}