Hallo miteinander
Ich stehe vor folgendem Problem: Mein Python-Programm muss eine Reihe Websites nacheinander besuchen, die sich jeweils in der URL nur in Ziffern unterscheiden. Der Start liegt bei: http://www.test.xyz/0000?action=source und die letzte zu besuchende Seite ist (beispielsweise) http://www.test.xyz/9999?action=source.
Ursprünglich wollte ich das Problem via Integers lösen, nur: 0000 wird zu einer "simplen" 0, d.h. so funktioniert das ganze nicht.
Hat jemand eine Idee, wie man das hinbekommen könnte?
Besten Dank für jeden Input.
Marcel
Websites besuchen
Code: Alles auswählen
if __name__=="__main__":
url = ("http://www.test.xyz/", "?action=source")
for i in range(9999):
if len(str(i)) == 1:
i = "000"+str(i)
elif len(str(i)) == 2:
i = "00"+str(i)
elif len(str(i)) == 3:
i = "0"+str(i)
elif len(str(i)) == 4:
i = str(i)
name = "%s%s%s" % (url[0], i, url[1])
print name
@Dami123: Das ist wohl so das komplizierteste was machen machen kann (bevor es absurd wird). mcdwerner hat doch schon Zeichenkettenformatierung vorgeschlagen.
mcdwerner, danke vielmals für den Tipp!
Ich habe eine einfache Funktion erstellen können, die genau nun genau das macht, was ich wollte
Dami123, danke für das Beispiel. In der Zwischenzeit habe ich halt schon ein eigenes erstellt, aber es ist immer schön zu wissen, dass einem hier geholfen wird
Eine andere Frage hätte ich noch, sie betrifft BeautifulSoup:
BS4 ordnet die Attribute im XML automatisch alphabetisch. Gibt es eine Möglichkeit, das zu unterdrücken? Zudem fügt BS4 Endknoten (</table>) automatisch an vorherige Elemente an, obwohl ich eigentlich lieber einen Zeilenumbruch hätte.
Klar, das sind alles optische Details, die python selbst nicht stören. Aber trotzdem wolle ich die Frage hier kurz stellen
Ich habe eine einfache Funktion erstellen können, die genau nun genau das macht, was ich wollte
Dami123, danke für das Beispiel. In der Zwischenzeit habe ich halt schon ein eigenes erstellt, aber es ist immer schön zu wissen, dass einem hier geholfen wird
Eine andere Frage hätte ich noch, sie betrifft BeautifulSoup:
BS4 ordnet die Attribute im XML automatisch alphabetisch. Gibt es eine Möglichkeit, das zu unterdrücken? Zudem fügt BS4 Endknoten (</table>) automatisch an vorherige Elemente an, obwohl ich eigentlich lieber einen Zeilenumbruch hätte.
Klar, das sind alles optische Details, die python selbst nicht stören. Aber trotzdem wolle ich die Frage hier kurz stellen
@BlackJack
Ja das stimmt Habs aus nem alten Script kopiert.
Das funktioniert um einiges besser.
Ja das stimmt Habs aus nem alten Script kopiert.
Das funktioniert um einiges besser.
Code: Alles auswählen
for i in range(9999):
print "%04d" % i
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Hui... das hättest Du Dir überlegen sollen... das ist glatt etwas für The Daily WTFDami123 hat geschrieben:@BlackJack
Ja das stimmt Habs aus nem alten Script kopiert.
Bitte benutze doch in Zukunft für Python-Code die Python-Code-Tags [ python ] Code [ /python ] oder allgemein (für viele andere Sprachen) [ code=python ] Code [ /code ] (Ohne die Leerzeichen).
Da die Reihenfolge von Attributen in XML keiner Semantik unterliegt, wage ich das zu bezweifeln. Intern wird BS das auch sicher nicht ordnen, sondern erst bei der Ausgabe. Wenn BS API da einen Hook anbietet, bei dem man sich in die Formatierung einhängen kann, dann kannst Du das sicher ändern, wenn nein, dann nicht, außer Du schreibst Deine eigene Serialisierungs-Engine.MarcelF6 hat geschrieben: BS4 ordnet die Attribute im XML automatisch alphabetisch. Gibt es eine Möglichkeit, das zu unterdrücken?
Wobei dann die Frage ist, in welcher Reihenfolge Du sie haben willst? Ich könnte mir vorstellen, dass BS intern ein Dictionary für die Attribute verwendet; dann ist die ursprüngliche Reihenfolge eh futsch
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Ich habe doch noch eine Frage: Wie bekommt man (im HTML-File) inhaltsleere Tags gelöscht?
Beispiel: " <b></b> " soll einfach gelöscht werden.
Ich habe versucht, das html-File zu öffnen und dann nach "<b></b>" zu suchen und bei einem Fund es via re.sub() zu ignorieren.
Allerdings ohne Erfolg. Hätte jemand einen Vorschlag?
Beispiel: " <b></b> " soll einfach gelöscht werden.
Ich habe versucht, das html-File zu öffnen und dann nach "<b></b>" zu suchen und bei einem Fund es via re.sub() zu ignorieren.
Allerdings ohne Erfolg. Hätte jemand einen Vorschlag?
@MarcelF6: Du benutzt doch schon BeautifulSoup4 — also einfach die entsprechenden Elemente suchen und mit der `extract()`-Methode entfernen. Wobei man aufpassen muss was man entfernt, denn ein leeres `<a>` mit einem `id`-Attribut sollte man beispielsweise besser nicht entfernen.
Danke für den Hinweis.
Ich habe momentan diesen Code, und bin eigentlich der Meinung, dass es so klappen müsste. Allerdings habe ich im output-File immernoch die inhaltsleeren Tags <b></b>. Woran könnte das liegen bzw. was ist wie zu ändern?
Danke für alle Inputs
Ich habe momentan diesen Code, und bin eigentlich der Meinung, dass es so klappen müsste. Allerdings habe ich im output-File immernoch die inhaltsleeren Tags <b></b>. Woran könnte das liegen bzw. was ist wie zu ändern?
Danke für alle Inputs
Code: Alles auswählen
output = codecs.open("test.html", "a", "utf-8")
for i in range(0, 10):
nr = add_nulls(i, 4)
f = urllib2.urlopen('http://blubb.xyz')
html = f.read()
f.close()
soup = BeautifulSoup(html)
txt = ""
for text in soup.find_all("table", {'class': 'main'}):
txt += str(text)
txt = str(txt)
text = "\n".join(re.sub(r'\[:[\/]?T.*?:\]', '', el) for el in txt.splitlines())
bs = BeautifulSoup(text)
empty_tags = bs.find_all(lambda tag: tag.name == 'b' and tag.find(True) is None and (tag.string is None or tag.string.strip()==""))
[empty_tag.extract() for empty_tag in empty_tags]
output.write(text.decode("utf-8"))
@MarcelF6: Argh, ist das eine gruselige Mischung aus ordentlicher Verarbeitung eines Objektbaums und Zeichenkettenmurks. Und daran liegt es dann letztendlich auch. Du veränderst den Objektbaum, speicherst dann aber die unveränderte Zeichenkette aus welcher der Objektbaum erzeugt wurde.
Und „list comprehensions” sind zum Erzeugen von Listen da die man auch benutzen möchte, und nicht um sinnfreie Listen zu erzeugen die nicht verwendet werden. Das ist keine schicke Syntax um eine ``for``-Schleife in eine Zeile zu schreiben. Wobei man *das* auch ohne „list comprehension” machen könnte, aber aus Gründen der Lesbarkeit nicht sollte.
Und „list comprehensions” sind zum Erzeugen von Listen da die man auch benutzen möchte, und nicht um sinnfreie Listen zu erzeugen die nicht verwendet werden. Das ist keine schicke Syntax um eine ``for``-Schleife in eine Zeile zu schreiben. Wobei man *das* auch ohne „list comprehension” machen könnte, aber aus Gründen der Lesbarkeit nicht sollte.
Hm ok, ich sehe was du meinst.
Und genau bei der Speicherung der modifizierten Struktur habe ich Mühe: Wie kann man die modifizierte Struktur speichern?
Würdest du eine zusätzliche Variable einführen (=die modifizierte Struktur), und diese via output.write in das File speichern?
Danke für die Tipps!
Und genau bei der Speicherung der modifizierten Struktur habe ich Mühe: Wie kann man die modifizierte Struktur speichern?
Würdest du eine zusätzliche Variable einführen (=die modifizierte Struktur), und diese via output.write in das File speichern?
Danke für die Tipps!
@MarcelF6: Du hast die Struktur doch schon an einen Namen gebunden. Sonst hättest Du sie ja nicht verändern können.
Edit: Was soll denn eigentlich ``txt = str(txt)`` bewirken? Und wieso benutzt Du `codec.open()` wenn Du `str`-Werte speichern willst, die Du erst mit der gleichen Kodierung dekodierst, die das Dateiobjekt zum schreiben verwendet?
Edit: Was soll denn eigentlich ``txt = str(txt)`` bewirken? Und wieso benutzt Du `codec.open()` wenn Du `str`-Werte speichern willst, die Du erst mit der gleichen Kodierung dekodierst, die das Dateiobjekt zum schreiben verwendet?
Ah dumm; klar. Hab den Fehler entdeckt.
txt = str(txt) verwende ich, damit ich nachher die splitlines()-Funktion anwenden kann.
Den Punkt zur Codierung verstehe ich nicht ganz...
Ich habs nun so:
Was mich noch wunder nimmt: Jetzt wird die Ausgabe so gespeichert, dass sie "schön" zu lesen ist, d.h. mit Einzügen, sodass verschiedene Tags leicht auseinander gehalten werden können. Gibt es eine Möglichkeit, die Ausgabe ohne diese Einzüge zu speichern?
txt = str(txt) verwende ich, damit ich nachher die splitlines()-Funktion anwenden kann.
Den Punkt zur Codierung verstehe ich nicht ganz...
Ich habs nun so:
Code: Alles auswählen
text = BeautifulSoup(text)
empty_tags = text.find_all(lambda tag: tag.name == 'b' and tag.find(True) is None and (tag.string is None or tag.string.strip()==""))
[empty_tag.extract() for empty_tag in empty_tags]
output.write(text.decode("utf-8"))
@MarcelF6: Wieso solltest Du ohne ``txt = str(txt)`` die `splitlines()`-Methode denn *nicht* anwenden können? Und warum wendest Du die überhaupt an? Das ist völlig unnötig die Zeichenkette an Zeilenenden zu zerlegen, nur um sie nach dem ersetzen in den einzelnen Zeilen wieder mit Zeilenenden zusammen zu setzen.
Deine Lösung bindet jetzt den Namen `text` mal an Zeichenketten und mal an einen Objektbaum. Das ist verwirrend. Schon für erfahrene Programmierer, aber speziell auch für Dich, wo Du anscheinend sowieso schon unsicher bist was die Typen von Werten angeht.
Die falsche Verwendung von einer „list comprehension” hast Du immer noch.
Das Du Kodierungen nicht verstehst, sieht man am Quelltext. Du machst das unnötig umständlich und verwirrend. Du willst anscheinend UTF-8 als Zielkodierung. `str()` auf die `bs4`-Objekte ergibt UTF-8 kodierte Zeichenketten. Also genau das was Du haben willst. Aber Du dekodierst die mit UTF-8 in `unicode`-Objekte um sie einem `codecs`-Dateiobjekt zu übergeben, was die `unicode`-Objekte gleich wieder mit UTF-8 in Bytes umwandelt. Also dass was Du gerade vorher schon mal hattest. Der Schritt ist also völlig unnötig.
Genau wie Du Dir klar machen solltest welcher (Teil)ausdruck welchen Datentyp erzeugt, und damit welche Operationen möglich sind, solltest Du insbesondere bei `str` und `unicode` wissen welches davon vorliegt und bei `str` in welcher Kodierung.
Das die Ausgabe „schön” ist, liegt daran, dass die Eingabe schon „schön” ist. Wenn es kompakter sein soll, müsstest Du Textelemente die nur „whitespace” enthalten und direkt vor oder nach „block level”-Elementen (ausser <pre>) stehen, entfernen.
Deine Lösung bindet jetzt den Namen `text` mal an Zeichenketten und mal an einen Objektbaum. Das ist verwirrend. Schon für erfahrene Programmierer, aber speziell auch für Dich, wo Du anscheinend sowieso schon unsicher bist was die Typen von Werten angeht.
Die falsche Verwendung von einer „list comprehension” hast Du immer noch.
Das Du Kodierungen nicht verstehst, sieht man am Quelltext. Du machst das unnötig umständlich und verwirrend. Du willst anscheinend UTF-8 als Zielkodierung. `str()` auf die `bs4`-Objekte ergibt UTF-8 kodierte Zeichenketten. Also genau das was Du haben willst. Aber Du dekodierst die mit UTF-8 in `unicode`-Objekte um sie einem `codecs`-Dateiobjekt zu übergeben, was die `unicode`-Objekte gleich wieder mit UTF-8 in Bytes umwandelt. Also dass was Du gerade vorher schon mal hattest. Der Schritt ist also völlig unnötig.
Genau wie Du Dir klar machen solltest welcher (Teil)ausdruck welchen Datentyp erzeugt, und damit welche Operationen möglich sind, solltest Du insbesondere bei `str` und `unicode` wissen welches davon vorliegt und bei `str` in welcher Kodierung.
Das die Ausgabe „schön” ist, liegt daran, dass die Eingabe schon „schön” ist. Wenn es kompakter sein soll, müsstest Du Textelemente die nur „whitespace” enthalten und direkt vor oder nach „block level”-Elementen (ausser <pre>) stehen, entfernen.