Mechanize und BeautifulSoup

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@Sophus: was bekommst Du denn bei response.read() zurück?
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@Sirius3: Ich bekomme das zurück.
BlackJack

@Sirius3: Nur so als Anmerkung nebenbei: BeautifulSoup 4 hält sich mittlerweile an PEP8-Namensgebung, hat aber die alten Methoden noch aus Kompatibilitätsgründen. Bei neuem Code würde ich deshalb statt `fetchParents()` eher `find_parents()` vewenden. Es wurden also auch Methoden nicht nur in der Schreibweise angepasst, sondern auch umbenannt damit die API einheitlicher ist. Und wenn man sowieso nur das erste Element braucht, ginge auch `find_parent()`.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@Sophus: Bei Dir wird aus irgendwelchen Gründen das <p>-Tag vor <form> geschlossen, also ist es ja logisch, dass Du statt dem Parent-Element das Vorgänger-Element möchtest:

Code: Alles auswählen

soup.find("form", {"name":"register"}).find_previous('p').text
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@Sirius3: Ich benutze Python 2.7.6, ist das der Grund, weshalb es sich bei mir anders verhält als bei dir?
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@Sophus: da ich nur auf Deinen Quelltexten operiere scheint der Unterschied irgendwo bei Dir entstanden zu sein.

Erster Paste:

Code: Alles auswählen

<p>Sie muessen einen Benutzernamen angeben!<br />Sie muessen ein Passwort angeben!<br />Sie muessen eine E-Mail Adresse angeben!<br />Sie muessen das Feld PrivateKey erst ausfuellen!<br />Sie muessen das Feld ProgramName erst ausfuellen!<br /><form action="/example.php?adv_sent=registration" method="POST" name="register">   <table width="348" border="0" cellpadding="2">
Zweiter Paste:

Code: Alles auswählen

<p>Ihr Benutzername muss mindestens 3 Zeichen enthalten!<br/>Ihr Passwort muss mindestens 3 Zeichen enthalten!<br/>Sie haben eine ungueltige E-Mail angegeben!<br/>Sie muessen das Feld PrivateKey erst ausfuellen!<br/>Sie muessen das Feld ProgramName erst ausfuellen!<br/></p><form action="/example.php?adv_sent=registration" method="POST" name="register"> <table border="0" cellpadding="2" width="348">
Zwei völlig unterschiedliche Formatierungen bei anscheinend dem selben PHP-Skript? Zum Glück funktioniert find_previous komischerweise bei beiden Varianten. Das meinte ich mit "robust".
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@Sirius3: Ja, die Methode find_previous () funktioniert tatsächlich. Und weshalb ich hier zwei unterschiedliche Ergebnisse bekomme, verstehe ich genauso wenig.

Hatte ich beinahe vergessen: Danke 8)
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@Sophus: jetzt habe ich doch wieder die ganze Lösung präsentiert. Hast Du wenigstens kapiert, wie und warum die Lösung so ist? Fürs nächste mal. Nochmal drei Tage Diskussion halte ich nicht aus. :P
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@Sirius3: Hier meine Verständnis-Hausaufgabe.

Code: Alles auswählen

soup.find("form", {"name":"register"}).find_previous('p').text
Durch die find()-Methode wird durch die Datenstruktur bzw. durch den HTML-Baum der Webseite navigiert. Man hätte hier auch find_all() nehmen können, und im gesamten HTML-Baum suchen können. Da man hier aber genau weißt, wonach man sucht, und zwar die Form mit dem Namen register, so wäre es sinnvoller find() zu benutzen. Die find()-Methode setzt hier bei form an, und sucht dann im nächsten Schritt nach dem Schlüssel name, der dann mit dem Wert register im Zusammenhang steht. Aus diesem Grund wird innerhalb dieser Methode eine Dictionaries benutzt. Mit find_previous() wird vor dem Ergebnis der Methode find() geschaut, und zwar ab dem <p>-Tag, anschließend wird dann später das Ganze als Text über die Print-Anweisung ausgegeben.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Sophus hat geschrieben:(...) und zwar ab dem <p>-Tag, anschließend wird dann später das Ganze als Text über die Print-Anweisung ausgegeben.
Genauer gesagt: Mit dem `.text`-Attribut ist halt der nackte Text innerhalb der `<p>`-Tags gemeint.

Und der Unterschied zwischen `findall()` und `find()` ist halt, dass `findall()` alle Treffer als Sequenz (oder Generator, müsste ich jetzt nachsehen) liefert, während `find()` nur den ersten Treffer zurückgibt. `find()` ist verkürzt ausgedrückt sozusagen ein `findall()[0]` (bzw `next(findall())`.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@Sophus: es geht mir nicht darum, ob Du eine Zeile verstehst oder nicht verstehst. Du hilfst Dir selbst, wenn Du den Grund der Zeile verstehst. Warum wurde das Problem auf diese oder jene Weise gelöst und wie kann ich das gleiche Muster auf verwandte Probleme anwenden.

Zu Deinem Erklärungsversuch: würdest Du die Dokumentation lesen, würdest Du erfahren, dass find viele verschiedene Varianten beherrscht. Diese hier durchsucht auch den gesamten HTML-Baum und zwar nach form-Tags mit einem Attribut name das den Wert register hat und nimmt das erste, das es findet. Da wird also nichts angesetzt und es gibt auch keinen nächsten Schritt. Bei Deinen verqueren Erklärungen frage ich mich immer, ob Du tatsächlich so verquer denkst und das richtige meinst, oder ob Du einfach den Kern noch nicht verstanden hast.
Antworten