HTMLAgility Pack : 화면 긁기 클래스 이름에 하이픈이 포함 된 Div를 찾을 수 없습니까?

c# html-agility-pack screen-scraping

문제

이것은 일종의 학습 운동이지만 부분적으로는 '재미'입니다. 기본적으로 C # 콘솔 응용 프로그램에서 'Balcony'상태 룸 가격 (현재 $ 1039)의 가격을 파싱하려고합니다. URL은 다음과 같습니다.

http://www.carnival.com/BookingEngine/Stateroom/Stateroom2/?embkCode=PCV&itinCode=SC0&durDays=8&shipCode=SH&subRegionCode=CS&sailDate=08082015&sailingID=68791&numGuests=2&showDbl=False&isOver55=N&isPastGuest=N&stateCode=&isMilitary=N&evsel=&be_version=1

위의 URL을 잘로드했습니다.

var document = getHtmlWeb.Load(web_address);

Balcony 가격의 컨테이너는 ' col '클래스의 div이고 column-container clearfix 클래스의 세 번째 div입니다. 나는 내가 필요로 할 것 인 모든 것이 클래스와 함께 모든 div를 잘게 될 것이다라고 생각했다 :

var lowest_price = document.DocumentNode.SelectNodes("//div[@class='col-bottom']");

발코니 가격에 도달하려면 3 번 노드를 선택하십시오. 그러나 lowest_price 변수는 null을 계속 반환합니다. 나는 문서 자체가로드 된 것을 알고 나는 '내부를 볼 수 있습니다 col 내가'를 선택하면 ' col '. 그 div의 발견을 방해하고있는 col-bottom 의 하이픈입니까?

이것에 접근하는 다른 방법? 제가 말했듯이, 그것은 대부분 학습 훈련입니다. 그러나 화면 스크래핑이 필요한 맞춤형 모니터링 솔루션을 만들어야하므로 모든 것이 재미가 아닙니다.

감사!

관련 정보가 포함 된 HTML 스 니펫 편집 :

    <div class="col">
      <h2 data-cat-title="Balcony" class="uk-rate-title-OB"> Balcony </h2>   <p>&nbsp;</p>
        <div class="col-bottom">
        <h3> From</h3>
         <strong> $1,039.00* <span class="rate-compare-strike"> </span> </strong><a metacode="OB" href="#" class="select-btn">Select</a> </div>
    </div>

인기 답변

atrribute 이름 또는 값 thats 유효한 하이픈에있는 하이픈에 대한 잘못된 것은 없습니다. 소스의 문제점은 html을 렌더링하기 위해 클라이언트에서 javascript를 사용하고 html 페이지를 다운로드 할 수 있는지 확인하는 것입니다. 찾고 있지 않다.

자바 스크립트를 먼저 실행해야하는 페이지를 파싱하려면 웹 브라우저 컨트롤을 사용하고 html로 HTML을 전달하면됩니다.

다음은 WinForms 웹 브라우저 컨트롤을 사용하는 방법에 대한 간단한 예입니다.

private void ParseSomeHtmlThatRenderedJavascript(){
        var browser = new System.Windows.Forms.WebBrowser() { ScriptErrorsSuppressed = true };

        string link = "yourLinkHere";

        //This will be called when the web page loads, it better be a class member since this is just a simple demonstration
        WebBrowserDocumentCompletedEventHandler onDocumentCompleted = new WebBrowserDocumentCompletedEventHandler((s, evt) => {
            //Do your HtmlParsingHere
            var doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(browser.DocumentText);
            var someNode = doc.DocumentNode.SelectNodes("yourxpathHere");
        });

        //subscribe to the DocumentCompleted event using our above handler before navigating
        browser.DocumentCompleted += onDocumentCompleted;

        browser.Navigate(link);
    }

또한 Awesomium 및 기타 내장 웹 브라우저 컨트롤을 살펴볼 수도 있습니다.

또한 콘솔 응용 프로그램에서 WebBrowser를 실행하려는 경우 여기에 샘플이 있습니다. 사용하지 않는 경우에는 Windows 양식을 사용하고,이 샘플은 새 스레드의 WebBrowser 컨트롤에 도움이 됩니다.

    using System;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using HtmlAgilityPack;
    namespace ConsoleApplication276
    {

        // a container for a url and a parser Action
        public class Link
        {
            public string link{get;set;}
            public Action<string> parser { get; set; }
        }

        public class Program
        {

            // Entry Point of the console app
            public static void Main(string[] args)
            {
                try
                {
                    // download each page and dump the content
                    // you can add more links here, associate each link with a parser action, as for what data should the parser generate create a property for that in the Link container

                    var task = MessageLoopWorker.Run(DoWorkAsync, new Link() { 
                        link = "google.com", 
                        parser = (string html) => {

                            //do what ever you need with hap here
                            var doc = new HtmlAgilityPack.HtmlDocument();
                            doc.LoadHtml(html);
                            var someNodes = doc.DocumentNode.SelectSingleNode("//div");

                        } });


                    task.Wait();
                    Console.WriteLine("DoWorkAsync completed.");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("DoWorkAsync failed: " + ex.Message);
                }

                Console.WriteLine("Press Enter to exit.");
                Console.ReadLine();
            }

            // navigate WebBrowser to the list of urls in a loop
            public static async Task<Link> DoWorkAsync(Link[] args)
            {
                Console.WriteLine("Start working.");

                using (var wb = new WebBrowser())
                {
                    wb.ScriptErrorsSuppressed = true;

                    TaskCompletionSource<bool> tcs = null;
                    WebBrowserDocumentCompletedEventHandler documentCompletedHandler = (s, e) =>
                        tcs.TrySetResult(true);

                    // navigate to each URL in the list
                    foreach (var arg in args)
                    {
                        tcs = new TaskCompletionSource<bool>();
                        wb.DocumentCompleted += documentCompletedHandler;
                        try
                        {
                            wb.Navigate(arg.link.ToString());
                            // await for DocumentCompleted
                            await tcs.Task;
                            // after the page loads pass the html to the parser 
                            arg.parser(wb.DocumentText);
                        }
                        finally
                        {
                            wb.DocumentCompleted -= documentCompletedHandler;
                        }
                        // the DOM is ready
                        Console.WriteLine(arg.link.ToString());
                        Console.WriteLine(wb.Document.Body.OuterHtml);
                    }
                }

                Console.WriteLine("End working.");
                return null;
            }

        }

        // a helper class to start the message loop and execute an asynchronous task
        public static class MessageLoopWorker
        {
            public static async Task<Object> Run(Func<Link[], Task<Link>> worker, params Link[] args)
            {
                var tcs = new TaskCompletionSource<object>();

                var thread = new Thread(() =>
                {
                    EventHandler idleHandler = null;

                    idleHandler = async (s, e) =>
                    {
                        // handle Application.Idle just once
                        Application.Idle -= idleHandler;

                        // return to the message loop
                        await Task.Yield();

                        // and continue asynchronously
                        // propogate the result or exception
                        try
                        {
                            var result = await worker(args);
                            tcs.SetResult(result);
                        }
                        catch (Exception ex)
                        {
                            tcs.SetException(ex);
                        }

                        // signal to exit the message loop
                        // Application.Run will exit at this point
                        Application.ExitThread();
                    };

                    // handle Application.Idle just once
                    // to make sure we're inside the message loop
                    // and SynchronizationContext has been correctly installed
                    Application.Idle += idleHandler;
                    Application.Run();
                });

                // set STA model for the new thread
                thread.SetApartmentState(ApartmentState.STA);

                // start the thread and await for the task
                thread.Start();
                try
                {
                    return await tcs.Task;
                }
                finally
                {
                    thread.Join();
                }
            }
        }
    }


아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.