2013-06-02 3 views
0

나는이 C# 코드를 실행 ...XPath로 (다른 사람의) 잘못 코딩 된 HTML을 파헤 치는 데 어떻게 사용할 수 있습니까?

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Text.RegularExpressions; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
using System.IO; 
using System.Net; 
using System.Dynamic; 
using HtmlAgilityPack; 

namespace entropedizer 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     public String postRequest(string url, string eventTarget) 
     { 
      // A "pre-request," sent to gather SessionID and POST data parameters for the main request 
      HttpWebRequest prequest = (HttpWebRequest)WebRequest.Create("http://www.entropedia.info/Chart.aspx?chart=Chart"); 
      HttpWebResponse presponse = (HttpWebResponse)prequest.GetResponse(); 
      Stream pstream = presponse.GetResponseStream(); 
      StreamReader psr = new StreamReader(pstream); 
      string phtml = psr.ReadToEnd(); 

      Match viewstate = Regex.Match(phtml, "id=\"__VIEWSTATE\".+/>"); 
      Match eventvalidation = Regex.Match(phtml, "id=\"__EVENTVALIDATION\".+/>"); 
      ASCIIEncoding encoding = new ASCIIEncoding(); 
      string postData = "__EVENTTARGET=" + eventTarget + "&__VIEWSTATE=" + Uri.EscapeDataString(viewstate.ToString().Substring(24, viewstate.Length - 28)) + "&__EVENTVALIDATION=" + Uri.EscapeDataString(eventvalidation.ToString().Substring(30, eventvalidation.Length - 34)); 
      byte[] data = encoding.GetBytes(postData); 

      // The main request, intended to retreive the desired HTML 
      HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.entropedia.info/Chart.aspx?chart=Chart"); 
      request.Method = "POST"; 
      request.ContentType = "application/x-www-form-urlencoded"; 

      request.CookieContainer = new CookieContainer(); 
      Cookie sessionId = new Cookie("ASP.NET_SessionId", Regex.Match(presponse.Headers.ToString(), "ASP.NET_SessionId=.+ d").ToString().Substring(18, Regex.Match(presponse.Headers.ToString(), "ASP.NET_SessionId=.+ d").Length - 21), "/", ".entropedia.info"); 
      request.CookieContainer.Add(new Uri("http://www.entropedia.info/Chart.aspx?chart=Chart"), sessionId); 

      Stream stream = request.GetRequestStream(); 
      stream.Write(data, 0, data.Length); 
      stream.Close(); 

      HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
      stream = response.GetResponseStream(); 

      StreamReader sr = new StreamReader(stream); 

      return sr.ReadToEnd(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      System.Net.ServicePointManager.Expect100Continue = false; 
      HtmlAgilityPack.HtmlDocument hChart = new HtmlAgilityPack.HtmlDocument(); 
      hChart.LoadHtml(postRequest("http://www.entropedia.info/Chart.aspx?chart=Chart", "ctl00%24ContentPlaceHolder1%24DG1%24ctl19%24ctl05")); 

      HtmlNodeCollection chartStrings = hChart.DocumentNode.SelectNodes("/"); 

      if (chartStrings != null) 
      { 
       foreach (HtmlNode i in chartStrings) 
       { 
        System.IO.File.WriteAllText("C:/Users/Admin/Desktop/WholeDocument.txt", i.OuterHtml); 
       } 
      } 
      else 
      { 
       MessageBox.Show("Error: Null item list."); 
      } 
     } 
    } 
} 

은 ... 다음 HTML은 텍스트 파일에 기록됩니다.

http://pastebin.com/FALerBWR

내가 신체 내에서 HTML의 chartStrings = hChart.DocumentNode.SelectNodes("/html/body"); 400 개 + 라인을 HtmlNodeCollection 내 C# 코드에서 줄을 변경

대신 텍스트 파일에 기록됩니다.

줄을 HtmlNodeCollection chartStrings = hChart.DocumentNode.SelectNodes("/html/body/form");으로 변경하면 단 한 줄의 코드 (특성이있는 양식 열기 태그) 만 텍스트 파일에 기록됩니다. 많은 줄을 써야합니다 (대부분의 문서). HtmlAgilityPack이 잘못된 HTML 태그로 인해 혼란 스럽습니다. 이 문제를 프로그램 적으로 해결할 수있는 방법이 있습니까? 나는 프로그램을 실행할 때마다 수동으로 HTML을 수정하고 싶지 않습니다!

답변

1

이것은 "디자인 상"의 행동입니다. FORM은 기본적으로 empty HTML 요소로 간주됩니다. 그 이유는 (내 대답을 확인) SO 여기에 설명되어 있습니다 HtmlAgilityPack -- Does <form> close itself for some reason?

그러나 이것은 또한 구성 할 수 있습니다, 당신은 다음과 같이 다르게 동작하는 파서를 지시해야합니다

HtmlAgilityPack.HtmlDocument hChart = new HtmlAgilityPack.HtmlDocument(); 

// remove all specific behaviors for the `FORM` element 
HtmlAgilityPack.HtmlNode.ElementsFlags.Remove("form"); 

hChart.LoadHtml(postRequest("http://www.entropedia.info/Chart.aspx?chart=Chart", "ctl00%24ContentPlaceHolder1%24DG1%24ctl19%24ctl05")); 
HtmlNodeCollection chartStrings = hChart.DocumentNode.SelectNodes("/");