Wyciaganie danych z plików html - wyrażenia regularne?

0

Mam tysiące plików html z danymi o pewnych produktach z których muszę wyciągną dane.

Zacznijmy od najłatwiejszej chyba części do wyciągnięcia czyli podstawowych danych o produkcie które są zapisane następująco

<dt>Product name:</dt>
<dd>tekst</dd>
<dt>Company:</dt>
<dd>tekst</dd>
<dt>Assembly version:</dt>
<dd>tekst</dd>
<dt>Test site:</dt>
<dd>tekst</dd>  

Tam gdzie jest tekst danej pozycji może też być ustawiony kolor tekstu

<dd class="green">tekst</dd>

Jak to najprościej powyciągać? Z wyrażeniami regularnymi u mnie raczej cienko. Mogę liczyć na jakieś podpowiedzi?

1
using System;
using System.Text;
using System.Text.RegularExpressions;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var input = @"<dt>Product name:</dt><dd>tekst1</dd>
            <dt>Company:</dt>asdf
            <dd>tekst2</dd>
            <dt>Assembly version:</dt>
            <dd>tekst3</dd>
            <dt>Test site:</dt>
            <dd>tekst4</dd>dupadupaupda<b>asdf</b>";

            var start = input.IndexOf("<dt>");
            var end = input.LastIndexOf("</dd>") + 5;
            input = input.Substring(start, end - start);

            var entries = input.Split(new string [] { "<dt>" }, System.StringSplitOptions.RemoveEmptyEntries);
            foreach (var entry in entries)
            {
                var internalEntry = entry.Split(new string[] { "</dd>", "<dd>", "</dt>" }, System.StringSplitOptions.RemoveEmptyEntries);
                var v = internalEntry[0].TrimEnd(':');
                var k = internalEntry[string.IsNullOrWhiteSpace(internalEntry[2]) ? 1 : 2];
                Console.WriteLine("{0}={1}", v, k);
            }
        }
    }
}
0

Próbowałem to zrobić w bardzo podobny sposób, myślałem jednak że za pomocą wyrażeń regularnych można to zrobić prościej i bardziej elegancko.

Dodałeś..

using System.Text.RegularExpressions;

ale żadnych wyrażeń regularnych nie użyłeś?

Ten kod działa ok ale przy takim wpisie..

<dd class="green">tekst</dd>

się wywali.

1

Tia, przez chwilę próbowałem regexem, ale odechciało mi się. Jednak jeśli ma łapać z atrybutami albo be, to już bez nich będzie straszna rzeźba. Kolejna iteracja:

using System;
using System.Text;
using System.Text.RegularExpressions;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var input = @"<dt>Product name:</dt><dd>tekst1</dd>
            <dt>Company:</dt>asdf
            <dd class='asdf'>tekst2</dd>
            <dt>Assembly version:</dt>
            <dd>tekst3</dd>
            <dt>Test site:</dt>
            <dd>tekst4</dd>dupadupaupda<b>asdf</b>";

            var start = input.IndexOf("<dt>");
            var end = input.LastIndexOf("</dd>") + 5;
            input = input.Substring(start, end - start);

            var entries = Regex.Split(input, "<dt[^>]*>", RegexOptions.IgnoreCase | RegexOptions.Multiline);
            foreach (var entry in entries)
            {
                if (!string.IsNullOrWhiteSpace(entry))
                {
                    var internalEntry = Regex.Split(entry, "</dd>|<dd[^>]*>|</dt>", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                    var v = internalEntry[0].TrimEnd(':');
                    var k = internalEntry[string.IsNullOrWhiteSpace(internalEntry[2]) ? 1 : 2];
                    Console.WriteLine("{0}={1}", v, k);
                }
            }

        }
    }
}
0

HtmlAgilityPack - masz tam funkcje, które w bardzo wygodny sposób podzielą html na odpowiednie części. Przy okazji ŁF, odpowiadając na Twoje pytanie z innego postu, to (przynajmniej według mnie) wykorzystanie zewnętrznych dllek w kodzie ma się tak do programowania obiektowego, że po prostu nie wynajdujemy koła od nowa (tworząc często paskudny kod), a wykorzystujemy to co zostało zrobione przez dużo bardziej doświadczonego programistę. Więc już offtopując całkiem w każdej książce o programowaniu obiektowym powinni dopisać czwarty fundament : Reusability, bo o tym zdaje się wiele osób niestety zapomina.

1
using System;
using System.Text.RegularExpressions;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main( string[] args )
        {
            string input = @"
<dt>Product name:</dt>
<dd>tekst</dd>
<dt>Company:</dt>
<dd class=""green"">tekst2</dd>
<dt>Assembly version:</dt>
<dd>tekst3</dd>
<dt class=""green"">Test site:</dt>
<dd>tekst4</dd>";

            Regex regex = new Regex(@"<dt.*?>(.*?)</dt>\s*?<dd.*?>(.*?)</dd>");

            var matches = regex.Matches(input);

            for(int i = 0; i < matches.Count; i++)
                Console.WriteLine("{0,-30}{1}", matches[i].Groups[1], matches[i].Groups[2]);
        
            Console.ReadLine();
        }
    }
}

Możesz też spróbować LINQ to XML.

1 użytkowników online, w tym zalogowanych: 0, gości: 1