Feedback

C# - HRTL-Wrapper für Websites

Veröffentlicht von am 22.11.2015
(0 Bewertungen)
Mithilfe des folgenden Snippets ist es möglich, Informationen einer Website zu parsen, zu speichern und anschließend systematisch auszuwerten. Dabei wird ein sogenannter "HRLT"-Wrapper (Head-Right-Left-Tail-Wrapper) verwendet.

Nach der Instanziierung der Klasse "HRLT_Wrapper" müssen Elemente angegeben werden, welche für die Informationen stehen, die sich auf der Website befinden. Dazu jeweils der Container vor und nach dem Element mit dem jeweiligen Versatz angegeben.

Beispiel:
class="col2">Autor</th>

Hier würde man z.B. "HLRT_Wrapper.Element("col2", 6, "<", 0);" angeben, um das Element "Autor" zu erhalten. Wichtig ist allerdings, dass das Ende des Strings ("<") nicht bereits vorher im Element auftaucht.

Hat man die Elemente angelegt, kann man die Methode "parseWebsite" mit der jeweiligen URL, einem Head- und Tail-String und beliebig vielen Elementen angeben. Der Head- und Tail-String geben jeweils an, ab wo und bis wohin der Quelltext durchsucht werden soll. Auch hier ist darauf zu achten, dass jeweils das erste Vorkommen des Strings im Quelltext verwendet wird.

1. Beispiel (parseDotnetSnippets):
Ausgabe der neuesten Snippets von "dotnet-snippets"

2. Beispiel (parseWDR2):
Ausgabe des aktuell gespielten Titels des Radiosenders WDR2
using System;
using System.Collections.Generic;
using System.Net;
using System.Web;

class HLRT_Wrapper
{
    WebClient webClient;
    public HLRT_Wrapper()
    {
        webClient = new WebClient();
    }

    public List<List<String>> parseWebsite(string address, string head, string tail, params Element[] elemente)
    {
        List<List<String>> result = new List<List<String>>();
            
        string source = HttpUtility.HtmlDecode(webClient.DownloadString(address));

        int leftIndex = source.IndexOf(head);
        int rightIndex = source.IndexOf(head);
        while (true)
        {
            for (int i = 0; i < elemente.Length; i++)
            {
                leftIndex = source.IndexOf(elemente[i].left, rightIndex + 1);
                rightIndex = source.IndexOf(elemente[i].right, leftIndex + 1);

                if (rightIndex > source.IndexOf(tail) || leftIndex == -1 || rightIndex == -1)
                    return result;

                string text = source.Substring(leftIndex + elemente[i].leftDistance, rightIndex - leftIndex - elemente[i].leftDistance - elemente[i].rightDistance);

                if (result.Count < i + 1)
                    result.Add(new List<String>());
                result[i].Add(text);
            }
        }
    }

    public class Element
    {
        public string left { get; set; }
        public int leftDistance { get; set; }
        public string right { get; set; }
        public int rightDistance { get; set; }

        public Element(string left, int leftDistance, string right, int rightDistance)
        {
            this.left = left;
            this.leftDistance = leftDistance;
            this.right = right;
            this.rightDistance = rightDistance;
        }
    }
}

public void parseDotnetSnippets()
{
    HLRT_Wrapper wrapper = new HLRT_Wrapper();

    HLRT_Wrapper.Element sprache = new HLRT_Wrapper.Element("col1\">", 6, "<", 0);
    HLRT_Wrapper.Element autor = new HLRT_Wrapper.Element("col2\">", 6, "<", 0);
    HLRT_Wrapper.Element url = new HLRT_Wrapper.Element("<a href=", 9, "\">", 0);
    HLRT_Wrapper.Element titel = new HLRT_Wrapper.Element(">", 1, "</a>", 0);

    List<List<String>> liste = wrapper.parseWebsite("http://dotnet-snippets.de/", "col3\">Titel", "</table>", sprache, autor, url, titel);
            
    for (int j = 0; j < liste[0].Count; j++)
    {
        for (int i = 0; i < liste.Count; i++)
            Console.Write(liste[i][j] + "\t");
        Console.WriteLine();
    }
}

public void parseWDR2()
{
    HLRT_Wrapper wrapper = new HLRT_Wrapper();

    HLRT_Wrapper.Element interpret = new HLRT_Wrapper.Element("strong", 7, "<", 1);
    HLRT_Wrapper.Element titel = new HLRT_Wrapper.Element("/strong", 8, "<", 0);

    List<List<String>> liste = wrapper.parseWebsite("http://www.wdr2.de/", "colored", "class=\"live", interpret, titel);

    for (int j = 0; j < liste[0].Count; j++)
    {
        for (int i = 0; i < liste.Count; i++)
            Console.Write(liste[i][j] + "\t");
        Console.WriteLine();
    }
}
Abgelegt unter Website, Parser, Wrapper.

2 Kommentare zum Snippet

Anonymous2 schrieb am 22.11.2015:
Sobald man die Reihenfolge der Elemente ändert, funktioniert das "Parsen" nicht mehr:

parseWebsite("http://dotnet-snippets.de/", "col3\">Titel", "</table>", url, autor, sprache, titel)


Schau dir mal das HtmlAgilityPack in Verbindung mit XPath Ausdrücken an, das ist failsafer. :)
Maximilian Müller schrieb am 23.11.2015:
Das ist korrekt, der Startindex des 2. Elements liegt nach dem Endindex des 1. Elements, deshalb funktioniert es nur mit der Reihenfolge, wie sie auch im Quelltext ist.
Man könnte das Ganze so umschreiben, dass die Reihenfolge egal wäre, allerdings befinden sich manchmal zwischen den Elementen nicht eindeutige Identifier, sodass man sich sozusagen von Element zu Element hangelt.

Das HtmlAgilityPack kannte ich tatsächlich noch nicht, das wirkt auf jeden Fall deutlich besser und professioneller als mein Code. :-)
 

Logge dich ein, um hier zu kommentieren!