Frage

Ich habe meinen Code erneut überprüft und mir vergleichbare Vorgänge beim Öffnen einer URL angesehen, um Webdaten an Beautiful Soup zu übergeben. Aus irgendeinem Grund gibt mein Code einfach nichts zurück, obwohl er in der richtigen Form ist:

>>> from bs4 import BeautifulSoup

>>> from urllib3 import poolmanager

>>> connectBuilder = poolmanager.PoolManager()

>>> content = connectBuilder.urlopen('GET', 'http://www.crummy.com/software/BeautifulSoup/')

>>> content
<urllib3.response.HTTPResponse object at 0x00000000032EC390>

>>> soup = BeautifulSoup(content)

>>> soup.title
>>> soup.title.name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'name'
>>> soup.p
>>> soup.get_text()
''

>>> content.data
a stream of data follows...

Wie gezeigt, ist es klar, dass urlopen () eine HTTP-Antwort zurückgibt, die vom variablen Inhalt erfasst wird. Es ist sinnvoll, dass sie den Status der Antwort lesen kann, aber nachdem sie an Beautiful Soup übergeben wurde, werden die Webdaten nicht konvertiert in ein schönes Suppenobjekt (variable Suppe).Sie können sehen, dass ich versucht habe, ein paar Tags und Text zu lesen, der get_text () gibt eine leere Liste zurück, das ist seltsam.

Seltsamerweise, wenn ich über Inhalte auf die Webdaten zugreife.daten, die Daten werden angezeigt, aber es ist nicht nützlich, da ich keine schöne Suppe zum Parsen verwenden kann.Was ist mein Problem?Danke.

War es hilfreich?

Lösung

Wenn Sie nur die Seite kratzen möchten, erhält der requests den Inhalt, den Sie benötigen:

generasacodicetagpre.

Andere Tipps

urllib3 gibt ein Antwortobjekt zurück, das das enthält .data welches die vorgespannte Körpernutzlast hat.

Gemäß dem oberen Schnellstart anwendungsbeispiel hier, Ich würde so etwas tun:

import urllib3
http = urllib3.PoolManager()
response = http.request('GET', 'http://www.crummy.com/software/BeautifulSoup/')

from bs4 import BeautifulSoup
soup = BeautifulSoup(response.data)  # Note the use of the .data property
...

Der Rest sollte wie vorgesehen funktionieren.

--

Ein wenig darüber, was in Ihrem ursprünglichen Code schief gelaufen ist:

Sie haben die gesamte response objekt eher als die Körperlast.Dies sollte normalerweise in Ordnung sein, da die response objekt ist ein dateiähnliches Objekt, außer in diesem Fall verbraucht urllib3 bereits die gesamte Antwort und analysiert sie für Sie, sodass nichts mehr übrig ist .read().Es ist, als würde man einen Dateizeiger übergeben, der bereits gelesen wurde. .data auf der anderen Seite wird auf die bereits gelesenen Daten zugegriffen.

Wenn Sie urllib3-Antwortobjekte als dateiähnliche Objekte verwenden möchten, müssen Sie das Vorladen von Inhalten wie folgt deaktivieren:

response = http.request('GET', 'http://www.crummy.com/software/BeautifulSoup/', preload_content=False)
soup = BeautifulSoup(response)  # We can pass the original `response` object now.

Jetzt sollte es wie erwartet funktionieren.

Ich verstehe, dass dies kein sehr offensichtliches Verhalten ist, und als Autor von urllib3 entschuldige ich mich.:) Wir planen zu machen preload_content=False der Standard eines Tages.Vielleicht irgendwann bald (Ich habe hier ein Problem geöffnet).

--

Eine kurze Notiz zu .urlopen vs .request:

.urlopen geht davon aus, dass Sie sich um die Codierung aller an die Anforderung übergebenen Parameter kümmern.In diesem Fall ist es in Ordnung zu verwenden .urlopen weil Sie der Anfrage keine Parameter übergeben, sondern im Allgemeinen .request erledigt die ganze zusätzliche Arbeit für Sie, damit es bequemer ist.

Wenn jemand bereit wäre, unsere Dokumentation in diesem Sinne zu verbessern, wäre das sehr dankbar.:) Bitte senden Sie eine PR an https://github.com/shazow/urllib3 und fügen Sie sich als Mitwirkender hinzu!

Wie gezeigt, ist es klar, dass urlopen() eine HTTP-Antwort zurückgibt, die vom Variableninhalt erfasst wird ...

Wie du angerufen hast content ist nicht der Inhalt, sondern ein dateiähnliches Objekt, aus dem Sie den Inhalt lesen können.BeautifulSoup nimmt so etwas gerne an, aber es ist nicht sehr hilfreich, es für Debugging-Zwecke auszudrucken.Lesen wir also den Inhalt tatsächlich vor, um das Debuggen zu erleichtern:

>>> response = connectBuilder.urlopen('GET', 'http://www.crummy.com/software/BeautifulSoup/')
>>> response
<urllib3.response.HTTPResponse object at 0x00000000032EC390>
>>> content = response.read()
>>> content
b''

Das sollte es ziemlich deutlich machen BeautifulSoup ist hier nicht das Problem.Aber weiter so:

… aber nach der Übergabe an Beautiful Soup werden die Webdaten nicht in ein Beautiful Soup-Objekt (Variable Suppe) konvertiert.

Ja tut es.Die Tatsache, dass soup.title gab dir None anstatt eine zu erhöhen AttributeError ist ein ziemlich guter Beweis, aber Sie können ihn direkt testen:

>>> type(soup)
bs4.BeautifulSoup

Das ist definitiv ein BeautifulSoup Objekt.

Wenn du vorbeikommst BeautifulSoup eine leere Zeichenfolge, was genau Sie zurückbekommen, hängt davon ab, welchen Parser er unter der Decke verwendet;Wenn es auf der Python 3.x-Standardbibliothek basiert, erhalten Sie eine html Knoten mit einem Leerzeichen head, und leer body, und sonst nichts.Wenn Sie also nach einem suchen title Knoten, es gibt keinen, und du bekommst None.


Wie beheben Sie das Problem?

Als die Dokumentation Sie verwenden "den niedrigsten Anruf für eine Anfrage, sodass Sie alle Rohdetails angeben müssen." Was sind diese rohen Details?Ehrlich gesagt, wenn Sie es noch nicht wissen, sollten Sie diese Methode nicht anwenden. Ihnen beibringen, wie Sie mit den Details unter der Haube umgehen urllib3 Bevor Sie überhaupt wissen, dass die Grundlagen Ihnen keinen Gefallen tun würden.

Eigentlich braucht man das wirklich nicht urllib3 hier überhaupt.Verwenden Sie einfach die mit Python gelieferten Module:

>>> # on Python 2.x, instead do: from urllib2 import urlopen 
>>> from urllib.request import urlopen
>>> r = urlopen('http://www.crummy.com/software/BeautifulSoup/')
>>> soup = BeautifulSoup(r)
>>> soup.title.text
'Beautiful Soup: We called him Tortoise because he taught us.'

Mein schöner Suppencode funktionierte in einer Umgebung (mein lokaler Maschine) und ergibt eine leere Liste in einem anderen (Ubuntu 14-Server).

Ich habe mein Problem gelöst, um die Installation zu ändern. Details in einem anderen Thread:

HTML-Analyse mit schönen Suppe gibt leere Liste

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top