Fehler HTML-Auslesung

  • VB.NET

Es gibt 32 Antworten in diesem Thema. Der letzte Beitrag () ist von AliveDevil.

    Danke für die neuen Hinweise.

    Die Sache mit dem XML-Parser ist wieder Neuland für mich. Da ich die Lottozahlen (bis einschl. Super 6) mit der ersten Variante auslesen kann, bin ich auf folgenden Gedanken gekommen.

    Kann man das Regex nicht dahin gehend erweitern, dass es die Tabelle der Glücksspirale beinhaltet. Da ich den Suchausdruck immer wieder abschneide, bleibt irgendwann die Tabelle übrig. Die Zahlen der Glückspirale haben immer feste Längen (erst 1-stellíg dann 2-stellig usw.). Auf Grund dieser Tatsache könnte ich dann den Ausdruck immer wieder Abschneiden und so die Zahlen rausfiltern.

    Edit: So, bevor das hier weitergeht, habe die Sache, wie in meiner letzten Mitteilung bereits angedacht, hin bekommen.

    Kann nun alle Zahlen online ermitteln und in meine Datenbank übernehmen. Hoffe das der Deutsche Lottoblock nun nicht die Struktur seiner Webseite ändert.

    Nochmals bedanke ich mich für die zahlreichen Hilfen, besonderen Dank geht an hal2000.
    Gruß Markus

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „hal2000“ ()

    Westerwälder schrieb:

    Hoffe das der Deutsche Lottoblock nun nicht die Struktur seiner Webseite ändert.

    Ich habe gerade beim Aufräumen des Projektordners das alte Projekt wiedergefunden. Natürlich ist genau das Zitierte eingetreten. Also habe ich mir der Spaß gemacht und eine neue Filterfunktion geschrieben. Falls es noch jemanden interessiert: Hier ist sie.

    VB.NET-Quellcode

    1. Dim xml As String
    2. Using wc As New WebClient() With {.Proxy = Nothing}
    3. xml = wc.DownloadString("http://lotto.de")
    4. End Using
    5. Dim i1 As Int32 = xml.IndexOf("<div class=""header-zahlen"">")
    6. Dim i2 As Int32 = xml.IndexOf("<table class=""clearfix"">")
    7. xml = xml.Substring(i1, i2 - i1)
    8. xml = "<root>" & xml & "</root>"
    9. xml = xml.Replace("&auml;", "ä").Replace("&euro;", "€")
    10. Dim doc As XDocument = XDocument.Parse(xml)

    Der XML-Parser akzeptiert den so vorgefilterten String. Die Zahlen können nun komfortabel mit LINQ-to-XML rausgefiltert werden. Beispiel für das Ziehungsdatum:

    VB.NET-Quellcode

    1. Dim zdate = (From div In doc...<div> Where div.@class = "form-row" Select div).First().<select>.<option>.First().@value

    Das Auslesen der gezogenen Zahlen sei dem Leser überlassen.
    Gruß
    hal2000
    Nun muss ich leider dieses alte Thema nochmals ausgraben.
    Der Deutsche Lottoblock hat seine Site abermals umgestellt. Bei den Angaben zur Glücksspirale werden nun jeweils die zwei letzten Gewinnklassen in einem "Block" angezeigt.
    Ich weiß nicht, ob es sich um einen Zeilenumbruch oder einen Absatz handelt.

    Folgender Code funktioniert nicht:

    VB.NET-Quellcode

    1. WebDokument.Replace(vbNewLine, "")
    2. WebDokument.Replace(vbLf, "")
    3. WebDokument.Replace(vbCr, "")
    4. WebDokument.Replace(vbCrLf, "")
    5. WebDokument.Replace(" ", "")


    Bekomme einfach keinen zusammenhängenden String.
    Gruß Markus
    Ui - das Thema ist ja schon ne ganze Weile her. Bisher ging es ja nur um das Auslesen der 6-aus-49-Zahlen. Mir ist aufgefallen, dass der String mittlerweile anders vorgefiltert werden muss:

    VB.NET-Quellcode

    1. xml = xml.Substring(xml.IndexOf("<div id=""zuqLotto"" style=""display: block;"">"))
    2. xml = xml.Remove(ClosingTagIndex(xml) + 6)

    ClosingTagIndex() ist eine Funktion, die das passende schließende Tag findet. Da es diese im Framework nicht gibt, kannst du alternativ bis zu IndexOf("<div id=""zuqKeno"" style=""display: none;"">") extrahieren - das ergibt dasselbe.

    Der Rest bleibt wie gehabt. Die GlücksSpirale habe ich mir nur kurz angesehen - das Prinzip sollte dasselbe sein. Das ist nur noch eine weitere LINQ-Abfrage auf einem wieder anders vorgefilterten Teilstring.
    Gruß
    hal2000
    Beim Lottoblock funktioniert es, die Probleme tauchen bei der Glücksspirale auf

    HTML-Quellcode

    1. <tr>
    2. <td class="td_left">V</td>
    3. <td>59362</td>
    4. <td>15,0 x</td>
    5. <td>5.000,00 &euro;</td>
    6. </tr>
    7. <tr class="odd">
    8. <td class="td_left">VI</td>
    9. <td>
    10. 964446 <br />
    11. 028105 </td>
    12. <td>4,0 x</td>
    13. <td>100.000,00 &euro;</td>
    14. </tr>
    15. <tr>
    16. <td class="td_left">VII</td>
    17. <td class="gwzQuoGSZahlen">
    18. 1301242 <br />
    19. 0232732 </td>
    20. <td>unbesetzt</td>
    21. <td>
    22. <b>mind. 7.500,00 &euro;<br /> mtl. Sofortrente</b>
    23. </td>
    24. </tr>

    Bis zur Gewinnklasse V kann ich die Zahlen korrekt auslesen.
    Bei den Gewinnklassen VI und VII sind Zeilenumbrüche enthalten, welche ich nicht rausgefiltert bekomme.
    Gruß Markus
    Hatte erst jetzt die Zeit, nochmal drüberzuschauen. Den Zeilenumbruch <br /> bekommst du weg, indem du ihn einfach vorher durch ein Sonderzeichen ersetzt:

    VB.NET-Quellcode

    1. .Replace("<br />", "|")

    Danach kannst du die Zeichenfolge zwischen den <td>-Tags auslesen, alle Whitespaces / Newlines entfernen und nach | splitten.
    Gruß
    hal2000
    ich frage mich wozu das ganze herumgespiele mit regex ...
    wieso machst du nicht dir und dem lotto-webserver weniger arbeit ?

    PHP-Quellcode

    1. <?php
    2. function getData($d, $m, $y)
    3. {
    4. $json = @file_get_contents("http://www.lotto.de/bin/6aus49_archiv?drawday=$y-$m-$d");
    5. return $json ? json_decode($json) : false;
    6. }
    7. $data = getData(20, 11, 2013);
    8. if (!$data) die("ungültiges datum");
    9. echo "<pre>";
    10. print_r($data);
    11. echo "</pre>";



    ich weiß dass es PHP ist, wollt aber nur zeigen, dass du das alles auch mittels einer kleineren schnelleren anfrage + json regeln kannst

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Agita“ ()

    Dann nutz nicht die Website, wie @Agita: bereits sagte, sondern das direkt angebotene API (Application Programming Interface).
    Die URL wurde ebenfalls schon genannt: http://www.lotto.de/bin/6aus49_archiv?drawday=yy-mm-dd. Hier ein Beispiel vom 2013-11-22 (Aufruf: ?drawday=13-11-22)
    Lang

    Quellcode

    1. {
    2. "2013-11-20":{
    3. "super6":{
    4. "spieleinsatz":"2448823.75",
    5. "quoten":[
    6. {
    7. "beschreibung":"6 richtige Endziffern",
    8. "klasse":1,
    9. "quote":"100000.00",
    10. "anzahl":1,
    11. "jackpot":null,
    12. "kurzbeschreibung":"6 Endz."
    13. }
    14. ,{
    15. "beschreibung":"5 richtige Endziffern",
    16. "klasse":2,
    17. "quote":"6666.00",
    18. "anzahl":15,
    19. "jackpot":null,
    20. "kurzbeschreibung":"5 Endz."
    21. }
    22. ,{
    23. "beschreibung":"4 richtige Endziffern",
    24. "klasse":3,
    25. "quote":"666.00",
    26. "anzahl":172,
    27. "jackpot":null,
    28. "kurzbeschreibung":"4 Endz."
    29. }
    30. ,{
    31. "beschreibung":"3 richtige Endziffern",
    32. "klasse":4,
    33. "quote":"66.00",
    34. "anzahl":1697,
    35. "jackpot":null,
    36. "kurzbeschreibung":"3 Endz."
    37. }
    38. ,{
    39. "beschreibung":"2 richtige Endziffern",
    40. "klasse":5,
    41. "quote":"6.00",
    42. "anzahl":17719,
    43. "jackpot":null,
    44. "kurzbeschreibung":"2 Endz."
    45. }
    46. ,{
    47. "beschreibung":"1 richtige Endziffer",
    48. "klasse":6,
    49. "quote":"2.50",
    50. "anzahl":164431,
    51. "jackpot":null,
    52. "kurzbeschreibung":"1 Endz."
    53. }
    54. ],
    55. "waehrung":"EUR",
    56. "gewinnzahlen":"813722"
    57. }
    58. ,"spiel77":{
    59. "spieleinsatz":"5632690.00",
    60. "quoten":[
    61. {
    62. "beschreibung":"richtige Gewinnzahl",
    63. "klasse":1,
    64. "quote":"0.00",
    65. "anzahl":0,
    66. "jackpot":"400741.30",
    67. "kurzbeschreibung":"7 Endz."
    68. }
    69. ,{
    70. "beschreibung":"6 richtige Endziffern",
    71. "klasse":2,
    72. "quote":"77777.00",
    73. "anzahl":4,
    74. "jackpot":null,
    75. "kurzbeschreibung":"6 Endz."
    76. }
    77. ,{
    78. "beschreibung":"5 richtige Endziffern",
    79. "klasse":3,
    80. "quote":"7777.00",
    81. "anzahl":17,
    82. "jackpot":null,
    83. "kurzbeschreibung":"5 Endz."
    84. }
    85. ,{
    86. "beschreibung":"4 richtige Endziffern",
    87. "klasse":4,
    88. "quote":"777.00",
    89. "anzahl":232,
    90. "jackpot":null,
    91. "kurzbeschreibung":"4 Endz."
    92. }
    93. ,{"beschreibung":"3 richtige Endziffern",
    94. "klasse":5,
    95. "quote":"77.00",
    96. "anzahl":2232,
    97. "jackpot":null,
    98. "kurzbeschreibung":"3 Endz."
    99. }
    100. ,{
    101. "beschreibung":"2 richtige Endziffern",
    102. "klasse":6,
    103. "quote":"17.00",
    104. "anzahl":21112,
    105. "jackpot":null,
    106. "kurzbeschreibung":"2 Endz."
    107. }
    108. ,{
    109. "beschreibung":"1 richtige Endziffer",
    110. "klasse":7,
    111. "quote":"5.00",
    112. "anzahl":206693,
    113. "jackpot":null,
    114. "kurzbeschreibung":"1 Endz."
    115. }
    116. ],
    117. "waehrung":"EUR",
    118. "gewinnzahlen":"6659826"
    119. }
    120. ,"history":{},
    121. "kw":47,
    122. "date":"2013-11-20",
    123. "game":"6 aus 49",
    124. "lotto":{
    125. "spieleinsatz":"23513995.00",
    126. "quoten":[
    127. {
    128. "beschreibung":"6 Richtige + SZ",
    129. "klasse":1,
    130. "quote":"0.00",
    131. "anzahl":0,
    132. "kurzbeschreibung":"6 + SZ"
    133. }
    134. ,{
    135. "beschreibung":"6 Richtige",
    136. "klasse":2,
    137. "quote":"0.00",
    138. "anzahl":0,
    139. "kurzbeschreibung":"6"
    140. }
    141. ,{
    142. "beschreibung":"5 Richtige + SZ",
    143. "klasse":3,
    144. "quote":"5008.30",
    145. "anzahl":85,
    146. "kurzbeschreibung":"5 + SZ"
    147. }
    148. ,{
    149. "beschreibung":"5 Richtige",
    150. "klasse":4,
    151. "quote":"2313.60",
    152. "anzahl":552,
    153. "kurzbeschreibung":"5"
    154. }
    155. ,{
    156. "beschreibung":"4 Richtige + SZ",
    157. "klasse":5,
    158. "quote":"133.90",
    159. "anzahl":3178,
    160. "kurzbeschreibung":"4 + SZ"
    161. }
    162. ,{
    163. "beschreibung":"4 Richtige",
    164. "klasse":6,
    165. "quote":"31.70",
    166. "anzahl":26789,
    167. "kurzbeschreibung":"4"
    168. }
    169. ,{
    170. "beschreibung":"3 Richtige + SZ",
    171. "klasse":7,
    172. "quote":"17.50",
    173. "anzahl":48430,
    174. "kurzbeschreibung":"3 + SZ"
    175. }
    176. ,{
    177. "beschreibung":"3 Richtige",
    178. "klasse":8,
    179. "quote":"9.50",
    180. "anzahl":399176,
    181. "kurzbeschreibung":"3"
    182. }
    183. ,{
    184. "beschreibung":"2 Richtige + SZ",
    185. "klasse":9,
    186. "quote":"5.00",
    187. "anzahl":347589,
    188. "kurzbeschreibung":"2 + SZ"
    189. }
    190. ],
    191. "zusatzzahl":null,
    192. "waehrung":"EUR",
    193. "superzahl":"5",
    194. "gewinnzahlen":["9", "16", "19", "24", "36", "42"]
    195. }
    196. ,"year":2013,
    197. "complete":1
    198. }
    199. }

    Sieht jetzt im ersten Moment relativ komplex und schwierig aus, nur ist dieser Schein trüglich.
    Ein Beispiel wie du das im .NET Framework nativ auslesen kannst:
    [VB.NET] [WCF] Verarbeitung von JSON Alternative dazu ist Json.NET.
    Die vmtl. einfachste Variante ist System.web.Script.Serialization.JavaScriptSerializer.DeserializeObject(string)
    Um aus dem angegebenen JSON (JavaScript Object Notation) eine Klasse für das .NET Framework zu erzeugen, kannst du dieses Tool nutzen. Hier musst du zwar die ein oder andere Veränderung durchführen, aber es sollte möglich sein, dies im .NET Framework zu gestalten. Dies gilt nur für den DataContractJsonSerializer und Json.NET, der JavaScriptSerializer benötigt keine Klasse um zu funktionieren.