2014-12-30 2 views
0

C#으로 htmlagilitypack을 사용하여 HTML 파서를 일반화하는 방법에 대한 제안이 필요합니다. 구문 분석 한 웹 페이지에는 직원 정보가 들어 있습니다. 그들 모두가) 이름, ID, 주소를 가지고, 여기에 전화 은 시간 d)를 작동 또는) 이메일 B) 팩스 C 표시되지 않을 수있는 필드) skypeid 있습니다C#에서 htmlagilitypack을 사용하여 다양한 HTML 구문 분석

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>[email protected]</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(); 

    .... 
    } 

Employee 1이 Employee와 다릅니다. 어떻게 일반 구문 분석기를 작성할 수 있습니까? 또한 'skypeid'태그가 없습니다.

감사 HR

답변

0

, skypeid는 "nowarp"속성을 포함하지 않기 때문에 당신은 "TD"(라벨) 및 "TD [@class]"(값)에 의해 기록을 분석해야한다는 것.

확인이 샘플 :

Employee 객체 단순히 다음 테이블을 통해 반복 제안

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>[email protected]</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(); 
    } 
} 
0

그래서 각 직원은 하나 개의 테이블에? 테이블의 각 행은 employee의 속성 중 하나이며, 첫 번째 열은 속성 이름 second입니다. 실제 값입니다. 내가 좋아하는 일부 직원 객체로이 퍼팅과 샷을 걸릴 것 :

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;} 
} 

이제 아래 사항과 같이 갈 것이 강하게 또한 시도 구문 분석에 입력 만 할 수 있습니다.
일부 엣지 케이스가 덮히 지 않을 수 있으며 코드가 깨질 수도 있습니다. 그러나 생각한 생각을하게됩니다. 샘플에서

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(); 
       } 
    .... 
    } 
} 
관련 문제