Seite 2 von 2

Re: Etwas auswählen und anklicken

Verfasst: Montag 30. Januar 2012, 12:29
von needsch
@BlackJack:
HTTP ist das einzige Protokoll, dessen Grundprinzip er hier kennen sollte. Die Einarbeitung in "Netzwerk-Protokolle" vorzuschlagen oder zu fordern ist IMO etwas überzogen. Die unteren Schichten des TCP/IP-Modells braucht er erstmal sowieso nicht zu kennen.

@ente:
Wenn die Nummer, nach der du suchst, in einem HTML-Code eingebettet ist, der nicht überall auf der Seite ständig auftaucht, dann wäre ein regulärer Ausdruck das einfachste:
"In computing, a regular expression provides a concise and flexible means for "matching" (specifying and recognizing) strings of text, such as particular characters, words, or patterns of characters."

Man kann reguläre Ausdrücke also dafür nutzen, bestimmte Muster in Strings (auch Byte-Strings) zu finden. In Python kann dafür das re-Modul genutzt werden.

Primitives Beispiel:

Code: Alles auswählen

import re

strings = ["Hallo ente!", "Tschüß ente!", "bla bla ...guten MoRgEn bruder... bla bla"]

# Das angegebene pattern passt auf alle Kombinationen von "hallo", "guten tag", "guten morgen",
# "guten abend" und einem beliebigen Wort, das nur aus Buchstaben besteht.
pattern = r"(?:hallo|guten tag|guten morgen|guten abend) [a-zA-Z]+"

for string in strings:
    match_obj = re.search(pattern, string, re.I) # re.I <-> case-insensitive

    if match_obj:
        print("Der string '%s' enthält eine Begrüßung!" % string)
    else:
        print("Der string '%s' enthält keine bekannte Begrüßung!" % string)
Ausgabe:

Code: Alles auswählen

Der string 'Hallo ente!' enthält eine Begrüßung!
Der string 'Tschüß ente!' enthält keine bekannte Begrüßung!
Der string 'bla bla ...guten MoRgEn bruder... bla bla' enthält eine Begrüßung!
Anderes Beispiel, um ganz bestimmte Teile eines Musters zu extrahieren (hier geheime Nummern aus einem HTML-Code):

Code: Alles auswählen

import re

from pprint import pprint

html = """
<html>
<head>
<title>bla bla bla</title>
</head>

<body>
<span class='secret-number'>1337</span>
<div id='irgendein-super-dummer-html-code'>
    <span class='secret-number'>42</span>
    <span class='tja-das-wird-nicht-klappen secret-number'>73</span>
</div>
</body>
</html>
"""

# In Klammern stehendes kann vom regulären Ausdruck separat erfasst und später ausgelesen werden.
pattern = r"<span class='secret-number'>([0-9]+)</span>"

matches = re.findall(pattern, html, re.I)
pprint(matches)
Ausgabe:

Code: Alles auswählen

['1337', '42']
Die dritte secret-number wird nicht erfasst, weil das angegebene Pattern fordert, dass exakt "<span id='secret-number'>" am Anfang steht. Wenn auch nur irgendein Leerzeichen anders gesetzt ist oder andere Hochkommata benutzt werden oder, wie in diesem Fall, irgendein zusätzlicher Text drinsteckt, dann wird es nicht klappen. Reguläre Ausdrücke wissen nichts von HTML - es werden einfach nur exakte Übereinstimmungen mit dem angegebenen Muster gesucht.

Da kann man sich dann sehr komplizierte reguläre Ausdrücke ("pattern") überlegen, die all das beachten. Das ist aber relativ anspruchsvoll und erfordert häufig eine Menge Erfahrung mit regulären Ausdrücken; die Syntax ist für Anfänger erstmal relativ kompliziert. In deinem Fall reicht aber vllt. schon etwas ganz simples. (Das pattern in meinem Beispiel ist ja jetzt auch nicht so mörder-schwer, oder?)

Das wäre das erste, was ich versuchen würde. Wenn du so etwas häufiger machst, solltest du aber vielleicht doch mal einen HTML-Parser ausprobieren. Damit ist auf Dauer auch angenehmer zu arbeiten.

Viele Grüße

EDIT: id-Attribute durch class-Attribute ersetzt. Danke @BlackJack.

Re: Etwas auswählen und anklicken

Verfasst: Montag 30. Januar 2012, 13:22
von Hyperion
@needsch: Musst Du den "neuen" denn gleich mit RegExps in Zusammenhang mit rekursivem Markup "verderben"? :twisted: Mal im Ernst, mit `lxml` geht das doch mindestens genaus so einfach:

Code: Alles auswählen

In [11]: import lxml.html                

In [12]: html = """                      
<html>
<head>
<title>bla bla bla</title>
</head>
<body>
<span id='secret-number'>1337</span>
<div id='irgendein-super-dummer-html-code'>
    <span id='secret-number'>42</span>
    <span id='tja-das-wird-nicht-klappen secret-number'>73</span>
</div>
</body>
</html>
"""

In [13]: doc = lxml.html.fromstring(html)

In [14]: [node.text for node in doc.xpath("//span[@id='secret-number']")]
Out[14]: ['1337', '42']
Natürlich kann man bei so einfachen Geschichten auch einen RegExp einsetzen; aber wenn man sich daran gewöhnt und nicht überblicken kann, wo die Grenzen dieser Technik liegen, dann gerät man schnell auf die "schiefe Bahn".

Re: Etwas auswählen und anklicken

Verfasst: Montag 30. Januar 2012, 13:40
von snafu
`lxml` kann übrigens auch direkt im XPath-Statement den Text rausfischen:

Code: Alles auswählen

doc.xpath("//span[@id='secret-number']/text()")

Re: Etwas auswählen und anklicken

Verfasst: Montag 30. Januar 2012, 14:08
von needsch
Hyperion hat geschrieben:@needsch: Musst Du den "neuen" denn gleich mit RegExps in Zusammenhang mit rekursivem Markup "verderben"? :twisted: Mal im Ernst, mit `lxml` geht das doch mindestens genaus so einfach:

Code: Alles auswählen

In [11]: import lxml.html                

In [12]: html = """                      
<html>
<head>
<title>bla bla bla</title>
</head>
<body>
<span id='secret-number'>1337</span>
<div id='irgendein-super-dummer-html-code'>
    <span id='secret-number'>42</span>
    <span id='tja-das-wird-nicht-klappen secret-number'>73</span>
</div>
</body>
</html>
"""

In [13]: doc = lxml.html.fromstring(html)

In [14]: [node.text for node in doc.xpath("//span[@id='secret-number']")]
Out[14]: ['1337', '42']
Stimmt, das ist deutlich schöner, danke für das Beispiel. Habe zu meinem Bedauern noch nie mit lxml oder allg. XPath gearbeitet. Ich muss das bei Gelegenheit unbedingt mal ausprobieren. Sonst Bildungslücke. :oops: Kommt auf die TODO. :)

Viele Grüße

Re: Etwas auswählen und anklicken

Verfasst: Montag 30. Januar 2012, 18:05
von lunar
@needsch: Wenn man mit HTTP arbeitet, muss man wissen, wie das Request-Response-Modell von HTTP funktioniert, und mithin auch, was eine TCP-Verbindung ist, wie sie zustande kommt, und wann sie wieder beendet wird. Es verlangt ja niemand, dass er die Headerdaten von TCP/IP auswendig lernt, aber eine grundlegende Vorstellung von der Funktionalität von TCP/IP ist mindestens hilfreich.

Re: Etwas auswählen und anklicken

Verfasst: Montag 30. Januar 2012, 20:03
von enteenteente
Okay vielen Dank, ich probier einfach mal aus, was mir so am ehesten gelingt :D
Wieso eigentlich immer "er"? Ich bin kein Mann :mrgreen:

Re: Etwas auswählen und anklicken

Verfasst: Montag 30. Januar 2012, 20:06
von /me
enteenteente hat geschrieben:Wieso eigentlich immer "er"? Ich bin kein Mann :mrgreen:
Wuff!

Re: Etwas auswählen und anklicken

Verfasst: Montag 30. Januar 2012, 20:35
von enteenteente
Haha :mrgreen:

Re: Etwas auswählen und anklicken

Verfasst: Montag 30. Januar 2012, 21:50
von lunar
@enteenteente: Oh, ein ES ;)

Re: Etwas auswählen und anklicken

Verfasst: Montag 30. Januar 2012, 22:02
von enteenteente
Haha :)
Woher weißt du das?!

Re: Etwas auswählen und anklicken

Verfasst: Montag 30. Januar 2012, 22:08
von problembär
enteenteente hat geschrieben:Na das ist ja mal freundlich!
Mach' Dir nichts draus, die sind hier halt so.

Für einfache Fälle des Durchsuchens von Strings braucht man in Python nicht unbedingt RegEx einzusetzen. Das geht auch schon so:

Code: Alles auswählen

a = "Hallo"

if "lo" in a:
    print("'lo' ist in dem String 'a'.")
Einfach und schön. :P

Re: Etwas auswählen und anklicken

Verfasst: Montag 30. Januar 2012, 22:16
von enteenteente
Gut zu wissen :)
Danke. Okay probiere ich aus :)

Re: Etwas auswählen und anklicken

Verfasst: Montag 30. Januar 2012, 22:20
von JonasR
Solange man sich richtig verhält sind alle nett zu einem :) So wie man es erwartet

Re: Etwas auswählen und anklicken

Verfasst: Dienstag 31. Januar 2012, 09:36
von BlackJack
@needsch: Ergänzend zu dem Beitrag von Hyperion mit `lxml.html`: Dein HTML ist ungültig, weil `id`\s a) eindeutig sein müssen, und b) keine Leerzeichen enthalten dürfen. Was Du da gemacht hast findet man aber üblicherweise so in `class`-Attributen. Und dann kann man mit der `cssselect()`-Methode ganz einfach alle drei Zahlen filtern:

Code: Alles auswählen

In [77]: html = """
   ....: <html>
   ....: <head>
   ....: <title>bla bla bla</title>
   ....: </head>
   ....: <body>
   ....:     <span class='secret-number'>1337</span>
   ....:     <div id='irgendein-super-dummer-html-code'>
   ....:         <span class='secret-number'>42</span>
   ....:         <span class='tja-das-wird-nicht-klappen secret-number'>73</span>
   ....:     </div>
   ....: </body>
   ....: </html>
   ....: """

In [78]: doc = lxml.html.fromstring(html)

In [79]: doc.cssselect('.secret-number')
Out[79]: 
[<Element span at 93bf9ec>,
 <Element span at 93bf86c>,
 <Element span at 93bf89c>]

In [80]: [node.text for node in doc.cssselect('.secret-number')]
Out[80]: ['1337', '42', '73']

Re: Etwas auswählen und anklicken

Verfasst: Dienstag 31. Januar 2012, 18:54
von Hyperion
@BlackJack: Ja, ich hatte mich auch ein wenig gewundert, dass da ein Beispiel mit ``id``s daher kam. Ich hatte zuvor ja auch eher CSS-Selektoren vorgeschlagen. Aber schön, dass Du auch diesen Ansatz gezeugt hast.

@problembär: Dein Einwand ist durchaus sinnvoll, aber nur dann, wenn man einen Teilstring kennt und wissen will, ob der in einem enthalten ist. In diesem Falle kennt die OP den String ja nicht, sondern will ihn herausfinden ;-)