Laden...

Auslesen und Ausgeben bestimmter ID/Abschnitte in html

Erstellt von scitch vor 8 Jahren Letzter Beitrag vor 8 Jahren 4.505 Views
S
scitch Themenstarter:in
16 Beiträge seit 2015
vor 8 Jahren
Auslesen und Ausgeben bestimmter ID/Abschnitte in html

Vorab:
Falls ich mich im falschen Themenbereich befinden sollte entschuldige ich mich Vorab und bitte um Verschiebung in den richtigen Bereich.

Ich versuche mich gerade daran etwas mehr über die Verknüpfung von Websites (insbesondere html) und das Auslesen der Selbigen zu lernen.

Dazu dachte ich es wäre eine gute Übung einfach mal von einem Webradio den aktuellen Sänger und das aktuelle Lied auszulesen. (Habe mir hierfür einfach mal planetradio.de ausgesucht)

Das html element kann ich nun inzwischen hiermit auslesen:

using (WebClient client = new WebClient()) 
            {
                               
                string htmlCode = client.DownloadString("http://www.planetradio.de/music/trackfinder.html");

                
                WebBrowser.NavigateToString(htmlCode);

Allerdings bekomme ich so ja "nur" das komplette html element....wenn ich nur den Titel und Artisten möchte müsste ich (wahrscheinlich? ...bin mir da nicht sicher)

Diesen Abschnitt speziell auslesen:

<div id="headerTracklistCurrentSong">
	
			<span id="headerTracklistCurrentSongArtist"><a href="music/trackfinder.html">LINKIN PARK x STEVE AOKI</a></span>
			<span id="headerTracklistCurrentSongTitle"><a href="music/trackfinder.html">A LIGHT THAT NEVER COMES</a></span>		
</div>

Für Hilfe/Erklärungen wie ich dies auslesen könnte wäre ich sehr dankbar.

Vielen Dank an Alle Antwortenden im Voraus. 😃

3.003 Beiträge seit 2006
vor 8 Jahren

Wurde gerade etwas ähnliches diskutiert:

Regex: Quelle enthält unterschiedliche Zahlenformate (mit und ohne Komma)

Kurzfassung:

  • du kannst das HTML als Text auffassen und
    a) per RegEx das suchen, was du willst
    b) irgendwelche wilden String-Operationen machen, die dir auch das suchen, was du willst
  • einen HTML-Parser benutzen, der das HTML quasi zum Objekt macht und dir Zugriff auf seine Elemente verschafft. Es gibt einen eingebauten HTML-Parser im .NET-Framework (mshtml), der ein paar Tücken hat, und auch einige externe Parser (tidy.NET, HTML Agility Pack), die auch ihre Tücken haben
  • von Hand oder mit einem Tool das HTML in XML umwandeln, und dann die sehr guten .NET-XML-Parser (XDocument, XmlDocument) benutzen

Bei einer einfachen Anwendung mit nur einem Ziel, wie bei dir, dürfte Punkt 1 naheliegend sein.

LaTino
EDIT; formatierung...bin offenbar zu doof für zwei verschachtelte Listen^^

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

S
scitch Themenstarter:in
16 Beiträge seit 2015
vor 8 Jahren

Hallo LaTino und Danke für deine Antwort. 🙂

Ich habe mich mal daran versucht und darauf aufbauend folgendes geschrieben:

 MatchCollection CurrentSongArtist = Regex.Matches(htmlCode, @"<span id=""headerTracklistCurrentSongArtist""< a href = ""music / trackfinder.html"" > (<span[^>](.+?)<\/span>)</span>");

Allerdings bekomme ich damit als Ausgabe nur

"Auflistung"

Könntest du mir eventuell auf die Sprünge helfen wo da mein Fehler liegt (als absoluter html-noob) oder ob ich damit völlig auf dem falschen Dampfer bin? =)

W
955 Beiträge seit 2010
vor 8 Jahren

Hallo,

sieht so aus als ob mehr als ein Objekt zurückgegeben wurde. Am besten Du schaust mal mit dem Debugger rein.

S
scitch Themenstarter:in
16 Beiträge seit 2015
vor 8 Jahren

Hallo witte, Danke auch für deine Antwort.

Wenn ich mit dem Debugger reinschaue bekomme ich für CurrentSongArtist nur "null" ausgegeben....deswegen dachte ich dass eventuell etwas an meinem Code bzw. der MatchCollection nicht stimmt was ich nicht sehe. =)

S
417 Beiträge seit 2008
vor 8 Jahren

Hi,

ich würde das nicht mit Regex lösen, sondern mit einer speziellen HTML-Parser library, z.B. AngleSharp (https://github.com/AngleSharp/AngleSharp)
Hier kannst du dann auch Query selektoren angeben, um einfach an HTML-Elemente zu gelangen, z.B. bei dir zu einem span mit der id headerTracklistCurrentSongArtist.

S
scitch Themenstarter:in
16 Beiträge seit 2015
vor 8 Jahren

Hallo Sarc und Danke auch für deine Antwort.

Ich versuche eben einfach mal einen Einstieg zu bekommen....wie genau benutze ich denn AngleSharp bzw. wie kann ich es in mein existierendes Projekt einbinden...?

S
417 Beiträge seit 2008
vor 8 Jahren

Am einfachsten ist, wenn du über den NuGet Package manager nach AngleSharp suchst und es hierüber einbindest.
Beispiele zur Anwendung findest du unter: https://github.com/AngleSharp/AngleSharp/wiki/Examples

S
scitch Themenstarter:in
16 Beiträge seit 2015
vor 8 Jahren

Danke nochmal für deine Antwort.

Das Einbinden hat schonmal funktioniert. 😉

Am Code habe ich mich nun nochmal versucht aber eventuell bin ich auch gerade einfach zu kaputt um zu verstehen was gemeint war.

Ich dachte eigentlich dass es so gehen müsste:

string htmlCode = client.DownloadString("http://www.planetradio.de/music/trackfinder.html");

                
                var parser = new HtmlParser();
                var document = parser.Parse(htmlCode);
                
                var blueListItemsLinq = document.All.Where(m => m.LocalName == "span" && m.Id == "headerTracklistCurrentSongArtist");

                foreach (var item in blueListItemsLinq)


                    label.Content = item.TextContent;

Allerdings scheine ich da wohl einen Fehler gemacht zu haben...oder es schlichtweg falsch verstanden? 🙁

S
scitch Themenstarter:in
16 Beiträge seit 2015
vor 8 Jahren

Hallo nochmal zusammen.

Inzwischen bin ich wenigstens so weit einen Titel und Sänger auslesen zu können.

Mein Code bisher dazu ist jetzt:

WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;

           using (WebClient client = new WebClient()) 
            {
                client.DownloadFile("http://www.planetradio.de/music/trackfinder.html", @"C:\localfile.html");


                string htmlCode = client.DownloadString("http://www.planetradio.de/music/trackfinder.html");
                
                var parser = new HtmlParser();
                var document = parser.Parse(htmlCode);
                
                
                var hitfinderTable = document.All.Where(m => m.Id == "hitfindertable").First() as AngleSharp.Dom.Html.IHtmlTableElement;

                foreach (var row in hitfinderTable.Rows)
                {
                    var artistName = row.Cells[2].TextContent;
                    var songName = row.Cells[3].TextContent;
                    label.Content = artistName + " " + songName;
                }
                
            }

Allerdings bekomme ich damit immer nur den vor 5 Liedern gespielten Song zurück....also den letzten in der Liste des "trackfinder"....könnte mir jemand dabei helfen den aktuellen (also den ersten) Titel auszulesen?
(ich dachte dass dies mit "hitfindertable").First() gelöst wäre aber dem ist leider nicht so... 🙁

S
417 Beiträge seit 2008
vor 8 Jahren

Hi,

das Auslesen passt schon, allerdings überschreibst du ja den label.Content immer wieder, wodurch das Label natürlich immer den Text des letzten Elements enthält.

Mach einfach hitfinderTable.Rows.First() und lies dir nur hierzu die jeweiligen Tabellenzellen aus.

S
scitch Themenstarter:in
16 Beiträge seit 2015
vor 8 Jahren

Hallo Sarc und Danke für deine Antwort.

Damit hat es nun bei mir geklappt, Danke! 🙂

Das foreach habe ich nun rausgeschmissen und hiermit ersetzt:

var hitfinderTable = document.All.Where(m => m.Id == "hitfindertable").First() as AngleSharp.Dom.Html.IHtmlTableElement;

                
                    var zeile = hitfinderTable.Rows.First();
                    var artistName = zeile.Cells[2].TextContent;
                    var songName = zeile.Cells[3].TextContent;
                    
                    label.Content = artistName + " " + songName;

Danke an Alle, jetzt muss ich nur rausfinden wie ich es automatisch aktualisieren lassen kann. =)

2.207 Beiträge seit 2011
vor 8 Jahren

Hallo scitch,

das ist so ein Fehler, den du auch mit dem [Artikel] Debugger: Wie verwende ich den von Visual Studio? rausgefunden hättest.

Gruss

Coffeebean

P
52 Beiträge seit 2015
vor 8 Jahren

[..] jetzt muss ich nur rausfinden wie ich es automatisch aktualisieren lassen kann. =)

Eventuell per Timer? Zumindest könnte man es erneut laden lassen, vielleicht gibt es aber auch eine bessere Lösung.

        private static void Playlist()
        {
            try
            {
                // Dein Code
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

Code per Playlist(); an jeder benötigten Stelle abrufbar, keine Ahnung ob das hier das gesuchte war.

**:::

Gruß Padman
S
scitch Themenstarter:in
16 Beiträge seit 2015
vor 8 Jahren

Hallo Padman und Danke für deine Antwort.

Ja zu dem Schluss einen DispatcherTimer dafür zu nutzen bin ich dann nach einigem Suchen schlussendlich auch gekommen. 😉

Allerdings funktioniert es momentan noch nicht so ganz.
Der Timer läuft zwar, allerdings wird das Label nicht geupdatet....woran das liegt weiss ich allerdings leider (noch) nicht. 🤔


public partial class MainWindow : Window
    {
        DispatcherTimer Zeitgeber = new DispatcherTimer();

        int Zeitbeginn = 0;

        public MainWindow()
        {
            InitializeComponent();
            WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;

            Zeitgeber.Interval = new TimeSpan(0, 0, 0, 1, 0);
            Zeitgeber.Tick += new EventHandler(Zeitgeber_Tick);
            Zeitgeber.Start();
  }

        private void Zeitgeber_Tick(object sender, EventArgs e)
        {
            zeitanzeigenBlock.Text = Zeitbeginn++.ToString();
            label.Content = "";

            
            using (WebClient client = new WebClient())
            {

                string htmlCode = client.DownloadString("http://www.planetradio.de/music/trackfinder.html");

                var parser = new HtmlParser();
                var document = parser.Parse(htmlCode);


                var hitfinderTable = document.All.Where(m => m.Id == "hitfindertable").First() as AngleSharp.Dom.Html.IHtmlTableElement;


                var zeile = hitfinderTable.Rows.First();
                var artistName = zeile.Cells[2].TextContent;
                var songName = zeile.Cells[3].TextContent;

                label.Content = artistName + " " + songName;

            }
}

Viele Grüße 🙂

16.834 Beiträge seit 2008
vor 8 Jahren

Als Hinweis: Der Event des DispatcherTimer wird im UI Thread ausgeführt.
Der Webrequest bei Dir ist also auch im UI Thread. Früher oder später (eher früher) wirst Du merken, dass Deine GUI einfriert.
[FAQ] Controls von Thread aktualisieren lassen (Control.Invoke/Dispatcher.Invoke)

Der Debugger sollte Dir helfen das aktuelle Problem selbst heraus zu finden.
[Artikel] Debugger: Wie verwende ich den von Visual Studio?

P
52 Beiträge seit 2015
vor 8 Jahren

Und wie ist der aktuelle Stand?

Eine Frage: baust du nur eine reine Playlist-Abfrage oder auch einen Player ein?
Die URL zum Stream war sehr leicht zu finden 😉 :evil:

Der trackfinder scheint etwas hinterher zu sein, beim Stream werden die Daten normal geladen.

Edit Ich habe mal deinen Code genommen, bei mir wird das Label aktualisiert, GUI ist bisher noch nicht eingefroren. Ich hatte einiges zum Testen versucht, damit die Umlaute korrekt angezeigt werden, aber ohne Ergebnis, liegt das an AngleSharp?
Mit client.Encoding = Encoding.UTF8; klappte es nicht, egal welche Werte eingetragen wurden.

Ich habe mir ein Schnippsel ausgeliehen, damit die Wörter am Anfang groß geschrieben werden 😁

static string UppercaseWords(string value)
        {
            char[] array = value.ToCharArray();
            // Handle the first letter in the string.
            if (array.Length >= 1)
            {
                if (char.IsLower(array[0]))
                {
                    array[0] = char.ToUpper(array[0]);
                }
            }
            // Scan through the letters, checking for spaces.
            // ... Uppercase the lowercase letters following spaces.
            for (int i = 1; i < array.Length; i++)
            {
                if (array[i - 1] == ' ')
                {
                    if (char.IsLower(array[i]))
                    {
                        array[i] = char.ToUpper(array[i]);
                    }
                }
            }
            return new string(array);
        }

/* Aufruf
label.Content = UppercaseWords(artistName + " - " + songName);
\*/
Gruß Padman
S
4 Beiträge seit 2015
vor 8 Jahren

Hallo bei mir wird die Htmlparser Klasse nicht gefunden obwohl ich anglesharp eingebunden habe, woran könnte das liegen?

S
4 Beiträge seit 2015
vor 8 Jahren

Danke war ein Fehler von mir.

Komme gerade nicht weiter.

Was ist wenn ich Werte von verschiedenen Links einer Seite auslesen möchte und nur die Startseite angebe z.B www.google.de ? Die Lösung mit Webclient ist ja nur statisch und bezieht sich nur auf eine genau definierte Seite. Momentan wird wie im oberen Bsp. nur eine bestimmte url analysiert. Wie könnte ich dies für unterschiedliche Urls einer Seite realisieren, ohne für jede url einen neuen string zu erstellen.

5.658 Beiträge seit 2006
vor 8 Jahren

Hi simono,

Wie könnte ich dies für unterschiedliche Urls einer Seite realisieren, ohne für jede url einen neuen string zu erstellen.

Welchen String meinst du? Einen, der die URL enthält oder einen, der das RegEx-Muster enthält? Was sind deine genauen Anforderungen?

Christian

Weeks of programming can save you hours of planning

S
4 Beiträge seit 2015
vor 8 Jahren

Wahrscheinlich habe ich mich nicht optimal ausgedrückt. Es wird/kann ja immer nur der Code der mittels .Downloadstring geladen wird analysiert werden. Wie könnte ich das für alle Links einer Seite realisieren, ist das überhaupt möglich? Eventuell alle Links mithilfe eines Web Crawlers ziehen und dann einzeln analysieren.

16.834 Beiträge seit 2008
vor 8 Jahren

Dann musst Du das HTML nach allen Links durchforsten, schauen, welche Du davon schon überprüft hast, damit kein Ringverweis entsteht und das ganze Prozedere eben immer und immer wieder machen.
Je nachdem was Du dann damit anfängst ist das ganze legal oder nicht 😃