locked
Парсинг html c помощью htmlagility RRS feed

  • Вопрос

  • Пытаюсь пропарсить сайт, все правильно указал, но результата никакого 

    Теги выставлены правильно, поочередно, ничего перепутать не мог

    Пишется сие под wp8. 

    void codeSampleReq_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
            {
                try
                {
                    HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
                    htmlDoc.OptionFixNestedTags = true;
                    htmlDoc.LoadHtml(e.Result);
                    HtmlNode divContainer = htmlDoc.GetElementbyId("html/body[@class='black']/div[@id='wrapper']/div[@id='content']/div[@class='content']/div[@id='content-right']/div[@id='block-broadcasts']/div[@class='block-content']");
                    if (divContainer != null)
                    {
                        HtmlNodeCollection nodes = divContainer.SelectNodes("//table/tbody[@class='broadcasts-all']");
                        foreach (HtmlNode trNode in nodes)
                        {
                            CodeSample newSample = new CodeSample();
                            HtmlNode titleNode = trNode.SelectSingleNode("tr[@title='']/td");
                            if (titleNode != null)
                            {
                                newSample.Title = titleNode.InnerHtml.Trim();
                            }                   
                            codes.Add(newSample);
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Unable to download" + ex.Message);
                }

    Код взят из примера, пример работает. 

    Подскажите пожалуйста в чем может быть проблема.

    7 мая 2014 г. 17:44

Ответы

  • Чёрт!..

    Мой вчерашний ответ продублировался. Сейчас решил удалить один дубликат. В итоге удалились оба.

    Что ж, повторю ответ. Вдруг автор темы его ещё не прочитал.

    -----

    В этой - divContainer.SelectNodes("/table") - происходит получение коллекции узлов table. В html действительно несколько таблиц? Если таблица всего одна, то семантически правильнее использовать метод SelectSingleNode.

    В узле с id = content-right первым вложенным элементов является div, затем ещё один div и лишь затем table. Следовательно, xpath должен выглядеть так: "/div/div/table". Можно написать проще: "//table" (два слэша), но при этом парсер будет проходить по всему поддереву узлов. Первый способ точнее определяет путь и работает быстрее, поэтому лучше использовать его, если возможно.

    Далее действуем по аналогии.

    • Помечено в качестве ответа VeryStupidFox 12 мая 2014 г. 8:00
    12 мая 2014 г. 6:58

Все ответы

  • GetElementbyId("html/body[@class='black']/div[@id='wrapper']/div[@id='content']/div[@class='content']/div[@id='content-right']/div[@id='block-broadcasts']/div[@class='block-content']");
    
    В самом деле ID элемента равен этой строке?
    7 мая 2014 г. 18:25
  • а как по вашему должны быть указаны пути?

    исрпавил по образу и подобию

    HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
                    htmlDoc.OptionFixNestedTags = true;
                    htmlDoc.LoadHtml(e.Result);
                    HtmlNode divContainer = htmlDoc.GetElementbyId("block-broadcasts");
                    if (divContainer != null)
                    {
                        HtmlNodeCollection nodes = divContainer.SelectNodes("//table/tr");
                        foreach (HtmlNode trNode in nodes)
                        {
                            CodeSample newSample = new CodeSample();
                            HtmlNode titleNode = trNode.SelectSingleNode("tr[@title='']/td");
                            if (titleNode != null)
                            {
                                newSample.Title = titleNode.InnerHtml.Trim();
                            }

    8 мая 2014 г. 2:11
  • Сложно давать советы, не видя html.

    Вот этот xpath - "//table/tr" - означает: пройтись по всем таблицам на любом уровне вложенности и получить первый элемент tr. Таблиц действительно несколько?

    Полагаю, нужно получить все строки в таблице, то есть xpath должен выглядеть так: "/table//tr".

    • Помечено в качестве ответа VeryStupidFox 10 мая 2014 г. 4:44
    • Снята пометка об ответе VeryStupidFox 11 мая 2014 г. 16:14
    8 мая 2014 г. 9:12
  • вот что пытаюсь вытянуть 

    <div id="content-right">
        <div class="block nobg block-broadcasts" id="block-broadcasts">
        <div class="header">
            <h2>Программа трансляций</h2>
            
        </div>
        
        <div class="block-content ">
            
    <table>
        <tbody class="broadcasts-all">
            <tr class="date">
            <td class="date" colspan="2">
                <span class="fleft">Воскресенье, 11 мая</span>
                            <a href="#" class="fright js-prem-click">Только премиум</a>
                        </td>
        </tr>
                                <tr class="odd" data-link="http://goodgame.ru/channel/gQp/45/" title="">
                <td class="date" data-date="1399783560">
                    <span class="time">08:46</span>
                                </td>
                <td>
                                    <h3><a href="http://goodgame.ru/channel/gQp/45/" title="++++ КИНЦО ++++ трансляция по Другое">++++ КИНЦО ++++</a></h3>
                    <span class="sign"><span class="flag flag-it" title="Италия"></span><span class="gameicon gameicon-steam" title="Steam"></span><a class="ct" href="http://goodgame.ru/team/2862/">[VAR]</a><a href="http://goodgame.ru/user/25318/">gQp.919</a></span>
                                </td>
            </tr>

    вот сам код для "вытягивания", все равно не идет

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Navigation;
    using Microsoft.Phone.Controls;
    using Microsoft.Phone.Shell;
    using Sen.HTMLParser.Resources;
    using System.Collections.ObjectModel;
    using HtmlAgilityPack;
    using System.IO.IsolatedStorage;
    using System.IO;
    using System.Text;
     
    namespace Sen.HTMLParser
    {
        public partial class MainPage : PhoneApplicationPage
        {
            ObservableCollection<CodeSample> codes = new ObservableCollection<CodeSample>();
            public MainPage()
            {
                InitializeComponent();
                this.Loaded += MainPage_Loaded;
            }
     
            void MainPage_Loaded(object sender, RoutedEventArgs e)
            {
                WebClient codeSampleReq = new WebClient();
                codeSampleReq.DownloadStringCompleted += codeSampleReq_DownloadStringCompleted;
                codeSampleReq.DownloadStringAsync(new Uri("http://goodgame.ru/announcement/"));
                CodeSamples.ItemsSource = codes;
            }
     
            void codeSampleReq_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
            {
                try
                {
                    HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
                    htmlDoc.OptionFixNestedTags = true;
                    htmlDoc.LoadHtml(e.Result);
                    HtmlNode divContainer = htmlDoc.GetElementbyId("content-right");
                    if (divContainer != null)
                    {
                        HtmlNodeCollection nodes = divContainer.SelectNodes("/table");
                        foreach (HtmlNode trNode in nodes)
                        {
                            CodeSample newSample = new CodeSample();
                            HtmlNode titleNode = trNode.SelectSingleNode("tr[@class='odd']/td/h3/a");
                            if (titleNode != null)
                            {
                                newSample.Title = titleNode.InnerHtml.Trim();
                            }
    codes.Add(newSample);
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Unable to download" + ex.Message);
                }
            }

    11 мая 2014 г. 16:12
  • Чёрт!..

    Мой вчерашний ответ продублировался. Сейчас решил удалить один дубликат. В итоге удалились оба.

    Что ж, повторю ответ. Вдруг автор темы его ещё не прочитал.

    -----

    В этой - divContainer.SelectNodes("/table") - происходит получение коллекции узлов table. В html действительно несколько таблиц? Если таблица всего одна, то семантически правильнее использовать метод SelectSingleNode.

    В узле с id = content-right первым вложенным элементов является div, затем ещё один div и лишь затем table. Следовательно, xpath должен выглядеть так: "/div/div/table". Можно написать проще: "//table" (два слэша), но при этом парсер будет проходить по всему поддереву узлов. Первый способ точнее определяет путь и работает быстрее, поэтому лучше использовать его, если возможно.

    Далее действуем по аналогии.

    • Помечено в качестве ответа VeryStupidFox 12 мая 2014 г. 8:00
    12 мая 2014 г. 6:58