Question

J'ai revérifié mon code et examiné des opérations comparables sur l'ouverture d'une URL pour transmettre des données Web dans Beautiful Soup. Pour une raison quelconque, mon code ne renvoie rien bien qu'il soit sous sa forme correcte :

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

Comme indiqué, il est clair que urlopen() renvoie une réponse HTTP qui est capturée par le contenu de la variable. Il est logique qu'elle puisse lire l'état de la réponse, mais une fois transmise à Beautiful Soup, les données Web ne sont pas converties. en un objet Belle Soupe (soupe variable).Vous pouvez voir que j'ai essayé de lire quelques balises et du texte, get_text() renvoie une liste vide, c'est étrange.

Étrangement, lorsque j'accède aux données Web via content.data, les données apparaissent mais ce n'est pas utile car je ne peux pas utiliser Beautiful Soup pour les analyser.Quel est mon problème ?Merci.

Était-ce utile?

La solution

Si vous voulez simplement gratter la page, requests obtiendra le contenu dont vous avez besoin:

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'

Autres conseils

urllib3 renvoie un objet Response, qui contient le .data qui a la charge utile du corps préchargée.

Selon le démarrage rapide supérieur exemple d'utilisation ici, je ferais quelque chose comme ceci :

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

Le reste devrait fonctionner comme prévu.

--

Un peu de ce qui n'a pas fonctionné dans votre code d'origine :

Vous avez réussi l'intégralité response objet plutôt que la charge utile du corps.Cela devrait normalement être bien parce que le response l'objet est un objet de type fichier, sauf dans ce cas, urllib3 consomme déjà toute la réponse et l'analyse pour vous, de sorte qu'il ne reste plus rien à faire. .read().C'est comme passer un pointeur de fichier déjà lu. .data d'autre part accédera aux données déjà lues.

Si vous souhaitez utiliser les objets de réponse urllib3 comme objets de type fichier, vous devrez désactiver le préchargement du contenu, comme ceci :

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

Maintenant, cela devrait fonctionner comme prévu.

Je comprends que ce n'est pas un comportement très évident, et en tant qu'auteur de urllib3, je m'en excuse.:) Nous prévoyons de faire preload_content=False la valeur par défaut un jour.Peut-être un jour bientôt (J'ai ouvert un numéro ici).

--

Un petit mot sur .urlopen contre .request:

.urlopen suppose que vous vous occuperez du codage de tous les paramètres transmis à la requête.Dans ce cas, c'est bien d'utiliser .urlopen parce que vous ne transmettez aucun paramètre à la requête, mais en général .request fera tout le travail supplémentaire pour vous, donc c'est plus pratique.

Si quelqu'un souhaite améliorer notre documentation à cet effet, ce serait grandement apprécié.:) Veuillez envoyer un PR à https://github.com/shazow/urllib3 et ajoutez-vous en tant que contributeur !

Comme indiqué, il est clair que urlopen() renvoie une réponse HTTP qui est capturée par la variable content…

Ce que tu as appelé content n'est pas le contenu, mais un objet semblable à un fichier à partir duquel vous pouvez lire le contenu.BeautifulSoup est parfaitement heureux de prendre une telle chose, mais il n'est pas très utile de l'imprimer à des fins de débogage.Alors, lisons le contenu pour faciliter le débogage :

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

Cela devrait indiquer assez clairement que BeautifulSoup ce n'est pas le problème ici.Mais on continue :

… mais une fois transmises dans Beautiful Soup, les données Web ne sont pas converties en un objet Beautiful Soup (soupe variable).

Oui.Le fait que soup.title vous a donné None au lieu de lever un AttributeError est une assez bonne preuve, mais vous pouvez la tester directement :

>>> type(soup)
bs4.BeautifulSoup

C'est définitivement un BeautifulSoup objet.

Quand tu passes BeautifulSoup une chaîne vide, ce que vous obtiendrez exactement dépendra de l'analyseur qu'il utilise sous les couvertures ;s'il s'appuie sur la stdlib Python 3.x, vous obtiendrez un html noeud avec un vide head, et vide body, et rien d'autre.Alors, quand vous cherchez un title nœud, il n'y en a pas, et vous obtenez None.


Alors, comment résoudre ce problème ?

Comme La documentation indique que vous utilisez « l’appel de niveau le plus bas pour faire une demande, vous devrez donc spécifier tous les détails bruts ». Quels sont ces détails bruts ?Honnêtement, si vous ne le savez pas déjà, vous ne devriez pas utiliser cette méthode pour vous apprendre à gérer les détails cachés de urllib3 avant même de connaître les bases, cela ne vous rendrait pas service.

En fait, tu n'as vraiment pas besoin urllib3 ici du tout.Utilisez simplement les modules fournis avec 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.'

Mon magnifique code de soupe fonctionnait dans un environnement (ma machine locale) et retourne une liste vide dans une autre (serveur Ubuntu 14).

J'ai résolu mon problème en modifiant l'installation. Détails dans Autre fil:

analyse HTML avec une belle soupe retourne la liste vide

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top