Domanda

Ho ricontrollato il mio codice e ho esaminato operazioni comparabili sull'apertura di un URL per passare i dati web in Beautiful Soup, per qualche motivo il mio codice non restituisce nulla sebbene sia in forma corretta:

>>> 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...

Come mostrato, è chiaro che urlopen () restituisce una risposta HTTP che viene catturata dal contenuto della variabile, ha senso che possa leggere lo stato della risposta, ma dopo che è passato in Beautiful Soup, i dati Web non vengono convertiti in un oggetto Beautiful Soup (variable soup).Puoi vedere che ho provato a leggere alcuni tag e testo, get_text() restituisce una lista vuota, questo è strano.

Stranamente, quando accedo ai dati web tramite il contenuto.data, i dati si presentano ma non è utile dal momento che non posso usare Beautiful Soup per analizzarlo.Qual è il mio problema?Grazie.

È stato utile?

Soluzione

Se vuoi solo raschiare la pagina, requests otterrà il contenuto di cui hai bisogno:

from bs4 import BeautifulSoup

import requests
r = requests.get('http://www.crummy.com/software/BeautifulSoup/')
soup = BeautifulSoup(r.content)

In [59]: soup.title
Out[59]: <title>Beautiful Soup: We called him Tortoise because he taught us.</title>

In [60]: soup.title.name
Out[60]: 'title'
.

Altri suggerimenti

urllib3 restituisce un oggetto di risposta, che contiene .data che ha il carico utile del corpo precaricato.

Per la parte superiore quickstart esempio di utilizzo qui, Farei qualcosa come questo:

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
...

Il resto dovrebbe funzionare come previsto.

--

Un po ' su cosa è andato storto nel tuo codice originale:

Hai superato l'intero response oggetto piuttosto che il carico utile del corpo.Questo dovrebbe normalmente andare bene perché il response object è un oggetto simile a un file, tranne in questo caso urllib3 consuma già tutta la risposta e la analizza per te, in modo che non rimanga nulla .read().È come passare un filepointer che è già stato letto. .data d'altra parte accederà ai dati già letti.

Se si desidera utilizzare gli oggetti di risposta urllib3 come oggetti simili a file, è necessario disabilitare il precaricamento del contenuto, in questo modo:

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

Ora dovrebbe funzionare come ti aspettavi.

Capisco che questo non è un comportamento molto ovvio, e come autore di urllib3 mi scuso.:) Abbiamo intenzione di fare preload_content=False il default un giorno.Forse un giorno presto (Ho aperto un problema qui).

--

Una breve nota su .urlopen vs .request:

.urlopen presuppone che si prenderà cura di codificare tutti i parametri passati alla richiesta.In questo caso va bene usare .urlopen perché non stai passando alcun parametro alla richiesta, ma in generale .request farà tutto il lavoro extra per te, quindi è più conveniente.

Se qualcuno volesse migliorare la nostra documentazione in tal senso, sarebbe molto apprezzato.:) Si prega di inviare un PR a https://github.com/shazow/urllib3 e aggiungetevi come contributore!

.

Come mostrato, è chiaro che urlopen () restituisce una risposta http che viene catturata dal contenuto della variabile ...

Quello che hai chiamato content non è il contenuto, ma un oggetto simile a file che puoi leggere il contenuto da. BeautifulSoup è perfettamente felice prendendo una cosa del genere, ma non è molto utile stamparlo per scopi di debug. Quindi, effettivamente leggiamo il contenuto per rendere questo più facile da eseguire il debug:

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

Questo dovrebbe renderlo abbastanza chiaro che BeautifulSoup non è il problema qui. Ma continuando su:

.

... Ma dopo che è passato nella bellissima zuppa, i dati del web non vengono convertiti in un bellissimo oggetto zuppa (zuppa variabile).

Sì lo fa. Il fatto che soup.title ti ha dato None invece di sollevare un AttributeError è una buona prova, ma puoi testarlo direttamente:

>>> type(soup)
bs4.BeautifulSoup
.

è sicuramente un oggetto BeautifulSoup.

Quando si passa BeautifulSoup una stringa vuota, esattamente ciò che recuperà dipenderà da quale parser sta usando sotto le coperte; Se si basa sul Python 3.x StDlib, ciò che otterrai è un nodo html con un head vuoto e vuoto body e nient'altro. Quindi, quando cerchi un nodo title, non ce n'è uno e ottieni None.


.

Allora, come risolvi questo?

come La documentazione Dice, stai usando "la chiamata di livello più bassa per effettuare una richiesta, quindi dovrai specificare tutti i dettagli grezzi." Quali sono quei dettagli grezzi? Onestamente, se non lo sai già, non dovresti usare questo metodo che ti insegna come affrontare i dettagli sotto-cappuccio di urllib3 prima di sapere anche che le basi non ti farebbero un servizio. In effetti, non hai davvero bisogno di urllib3 qui. Basta usare i moduli che vengono con Python:

>>> # 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.'
.

Il mio bellissimo codice di zuppa funzionava in un ambiente (la mia macchina locale) e restituire una lista vuota in un altro (server Ubuntu 14).

Ho risolto il mio problema cambiando l'installazione. Dettagli in Altro filo:

HTML Parsing con bellissima zuppa restituisce la lista vuota .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top