Пакет гибкости HTML

У меня есть таблицы html на одной веб-странице, например

<table border=1>
    <tr><td>sno</td><td>sname</td></tr>
    <tr><td>111</td><td>abcde</td></tr>
    <tr><td>213</td><td>ejkll</td></tr>
</table>

<table border=1>
    <tr><td>adress</td><td>phoneno</td><td>note</td></tr>
    <tr><td>asdlkj</td><td>121510</td><td>none</td></tr>
    <tr><td>asdlkj</td><td>214545</td><td>none</td></tr>
</table>

Теперь с этой веб-страницы, используя пакет гибкости html, я хочу извлечь данные адреса столбца и не только телефона. Это означает, что я сначала нашел, в какой таблице есть адрес столбца и phoneno. После нахождения этой таблицы я хочу извлечь данные этого адреса столбца и phoneno, что мне делать?

Я могу достать стол. Но после этого не понимаю, что мне делать.

И еще: возможно, мы можем извлекать данные из таблицы по имени столбца.


person Harikrishna    schedule 12.03.2010    source источник
comment
Дубликат stackoverflow.com/questions/2422762/html-agility-pack   -  person Mike Two    schedule 12.03.2010
comment
@Harikrishna - это тот же вопрос, который вы задали вчера. Вы заявляете об этом требовании во вчерашнем вопросе. Это все еще повторяющийся вопрос. Будет действительно проще, если вы сделаете исходный вопрос более ясным, вместо того, чтобы добавлять новые вопросы. У вас больше шансов получить желаемый ответ.   -  person Mike Two    schedule 12.03.2010
comment
@Harikrishna - Я понимаю вашу проблему с ответом, который я дал, и я не согласен с этим, но повторение того же вопроса - не способ получить лучший ответ.   -  person Mike Two    schedule 12.03.2010
comment
@Mike Two, сэр ... Большое спасибо, сэр, за помощь в моем предыдущем вопросе.   -  person Harikrishna    schedule 12.03.2010
comment
@Harikrishna - Пожалуйста, надеюсь, это было немного полезно. Удачи с вашим проектом.   -  person Mike Two    schedule 12.03.2010
comment
@Mike Two, сэр .. Большое спасибо, сэр ..   -  person Harikrishna    schedule 13.03.2010


Ответы (2)


Вот несколько вспомогательных методов, которые помогут вам разобрать HTML-таблицы на DataTable экземпляры. Вы можете просто просмотреть полученный массив DataTable, чтобы найти тот, который содержит нужные столбцы. Код связан с форматом таблиц в HTML, в этом случае он получает информацию о столбцах из первой строки (<tr>). Также обратите внимание, что проверка ошибок не выполняется, поэтому это приведет к поломке таблиц, которые не соответствуют указанному вами формату.

Вспомогательные методы:

private static DataTable[] ParseAllTables(HtmlDocument doc)
{
    var result = new List<DataTable>();
    foreach (var table in doc.DocumentNode.Descendants("table"))
    {
        result.Add(ParseTable(table));
    }
    return result.ToArray();
}

private static DataTable ParseTable(HtmlNode table)
{
    var result = new DataTable();

    var rows = table.Descendants("tr");

    var header = rows.Take(1).First();
    foreach (var column in header.Descendants("td"))
    {
        result.Columns.Add(new DataColumn(column.InnerText, typeof(string)));
    }

    foreach (var row in rows.Skip(1))
    {
        var data = new List<string>();
        foreach (var column in row.Descendants("td"))
        {
            data.Add(column.InnerText);
        }
        result.Rows.Add(data.ToArray());
    }
    return result;
}

Пример использования:

public static void Main(string[] args)
{
    string html = @"
        <html><head></head>
        <body><div>
            <table border=1>
                <tr><td>sno</td><td>sname</td></tr>
                <tr><td>111</td><td>abcde</td></tr>
                <tr><td>213</td><td>ejkll</td></tr>
            </table>
            <table border=1>
                <tr><td>adress</td><td>phoneno</td><td>note</td></tr>
                <tr><td>asdlkj</td><td>121510</td><td>none</td></tr>
                <tr><td>asdlkj</td><td>214545</td><td>none</td></tr>
            </table>
        </div></body>
        </html>";

    HtmlDocument doc = new HtmlDocument();

    doc.LoadHtml(html);

   DataTable addressAndPhones;
   foreach (var table in ParseAllTables(doc))
   {
       if (table.Columns.Contains("phoneno") && table.Columns.Contains("adress"))
       {
           // You found the address and phone number table
           addressAndPhones = table;
       }
   }
}
person João Angelo    schedule 12.03.2010
comment
@Harikrishna, Skip и Take определены в System.Linq. Вам нужно добавить оператор using для этого пространства имен. LINQ недоступен в .NET 2.0. - person João Angelo; 12.03.2010
comment
@Harikrishna, как я уже сказал, вспомогательные функции сильно связаны с заданным форматом HTML. Они работают для следующего примера. Если у вас есть разные входы, вам придется адаптировать их к своим потребностям. - person João Angelo; 12.03.2010
comment
@Joao Angelo, когда в таблице нет тега tr, такого как / tr, тогда он не анализирует эту информацию идеально, поэтому для этого я должен делать? Как и начальный тег tr, и новая строка начинается с нового начального тега tr без записи конечного тега tr. Есть ли в пакете гибкости html какая-либо опция, которая может сначала очистить страницу html, а затем проанализировать информацию. - person Harikrishna; 22.03.2010
comment
@Joao Angelo .. Спасибо за помощь. За отсутствующий закрывающий тег я использую прямо сейчас html tidy pack из-за отсутствия опции в html agility pack. - person Harikrishna; 25.03.2010
comment
@Joao Angelo, у меня есть одна серьезная проблема, и я пытаюсь ее решить уже много дней, иногда страница html может выглядеть так, как будто таблица не начинается с заголовка столбца, что я хочу, например, таблица начинается с другой информации, и я хочу скеплить их, но ошибка выглядит так: Сумма значений FillWeight столбцов не может превышать 65535. - person Harikrishna; 30.03.2010
comment
@Joao Angelo, что, если тег таблицы самый внутренний, как <table><tr><td></td><td><table><tr><td><td><table><tr><td><table>. Тогда я хочу извлечь самую внутреннюю таблицу - person Harikrishna; 31.03.2010

Перебирайте строки таблицы и получайте значения столбцов по индексу

int index = 0;
foreach(HtmlNode tablerow in table.SelectNodes("tr"))
{
    // skip the first row...
    if(index > 0)
    {
        // select first td element
        HtmlNode td1 = tablerow.SelectSingleNode("td[1]");
        if(td1 != null)
        {
            string address = td1.InnerText;
        }
    }
    index++;
}

Если вы можете изменить веб-страницу, вы можете использовать thead для текстов заголовков и tbody для фактических значений.

<table id="mytable">
    <thead><tr><td>Column1</td><td>Column2</td></tr></thead>
    <tbody>
        <tr><td>Value 1</td><td>Value 2</td></tr>
        <tr><td>Value 1</td><td>Value 2</td></tr>
    </tbody>
</table>

Тогда вам не пришлось бы пропускать первую строку.

foreach(HtmlNode tablerow in table.SelectNodes("/table[@id=\"mytable\"]/tbody/tr"))
{
    // ...
}

Взгляните на учебник по xpath, он очень полезен с HtmlAgilityPack.

person Mike Koder    schedule 12.03.2010