Pregunta

Volví a verificar mi código y observé operaciones comparables al abrir una URL para pasar datos web a Beautiful Soup, por alguna razón mi código simplemente no devuelve nada aunque está en la forma correcta:

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

Como se muestra, está claro que urlopen() devuelve una respuesta HTTP que es capturada por el contenido variable, tiene sentido que pueda leer el estado de la respuesta, pero después de pasarla a Beautiful Soup, los datos web no se convierten. en un objeto Beautiful Soup (sopa variable).Puedes ver que intenté leer algunas etiquetas y texto, get_text() devuelve una lista vacía, esto es extraño.

Curiosamente, cuando accedo a los datos web a través de content.data, los datos aparecen pero no son útiles ya que no puedo usar Beautiful Soup para analizarlos.¿Cuál es mi problema?Gracias.

¿Fue útil?

Solución

Si solo quieres raspar la página, requests Obtendrá el contenido que necesita:

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'

Otros consejos

urllib3 devuelve un objeto Respuesta, que contiene el .data que tiene la carga útil del cuerpo precargada.

Según el inicio rápido superior ejemplo de uso aquí, yo haría algo como esto:

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

El resto debería funcionar según lo previsto.

--

Un poco sobre lo que salió mal en tu código original:

Pasaste todo el response objeto en lugar de la carga útil del cuerpo.Esto normalmente debería estar bien porque el response el objeto es un objeto similar a un archivo, excepto en este caso, urllib3 ya consume toda la respuesta y la analiza por usted, de modo que no queda nada por hacer. .read().Es como pasar un puntero de archivo que ya ha sido leído. .data por otro lado accederá a los datos ya leídos.

Si desea utilizar objetos de respuesta urllib3 como objetos similares a archivos, deberá deshabilitar la precarga de contenido, de esta manera:

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

Ahora debería funcionar como esperabas.

Entiendo que este no es un comportamiento muy obvio y, como autor de urllib3, pido disculpas.:) Planeamos hacer preload_content=False el valor predeterminado algún día.Quizás algún día pronto (Abrí un problema aquí).

--

Una nota rápida sobre .urlopen vs .request:

.urlopen asume que usted se encargará de codificar cualquier parámetro pasado a la solicitud.En este caso está bien usar .urlopen porque no estás pasando ningún parámetro a la solicitud, pero en general .request hará todo el trabajo extra por usted para que sea más conveniente.

Si alguien quisiera mejorar nuestra documentación en este sentido, se lo agradeceríamos mucho.:) Por favor envíe un PR a https://github.com/shazow/urllib3 ¡Y agrégate como colaborador!

Como se muestra, está claro que urlopen() devuelve una respuesta HTTP que es capturada por el contenido variable...

lo que has llamado content no es el contenido, sino un objeto similar a un archivo desde el que puedes leer el contenido.BeautifulSoup está muy feliz de aceptar algo así, pero no es muy útil imprimirlo para fines de depuración.Entonces, leamos el contenido para que sea más fácil de depurar:

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

Esto debería dejar bastante claro que BeautifulSoup No es el problema aquí.Pero continuando:

… pero después de pasar a Beautiful Soup, los datos web no se convierten en un objeto Beautiful Soup (sopa variable).

Sí lo hace.El hecho de que soup.title te dio None en lugar de levantar un AttributeError Es una evidencia bastante buena, pero puedes probarla directamente:

>>> type(soup)
bs4.BeautifulSoup

Eso es definitivamente un BeautifulSoup objeto.

cuando pasas BeautifulSoup una cadena vacía, exactamente lo que obtenga dependerá del analizador que esté usando bajo las sábanas;si se basa en Python 3.x stdlib, lo que obtendrá es un html nodo con un vacío head, y vacío body, y nada más.Entonces, cuando buscas un title nodo, no hay ninguno, y obtienes None.


¿Entonces cómo lo arreglas?

Como la documentación Dice, está utilizando "la llamada de nivel más baja para hacer una solicitud, por lo que deberá especificar todos los detalles sin procesar". ¿Cuáles son esos detalles en bruto?Honestamente, si aún no lo sabes, no deberías usar este método. Enseñarte cómo lidiar con los detalles ocultos de urllib3 incluso antes de que sepas lo básico no te estaría haciendo ningún servicio.

De hecho, realmente no necesitas urllib3 aquí en absoluto.Simplemente use los módulos que vienen 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.'

Mi hermoso código de sopa estaba trabajando en un entorno (mi máquina local) y devolviendo una lista vacía en otro (Ubuntu 14 Server).

He resuelto mi problema cambiando la instalación. Detalles en otro hilo:

HTML Parsing con Hermosa sopa Devuelve Lista vacía

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top