156 votes

récupérer les liens d'une page web en utilisant python et BeautifulSoup

Comment puis-je récupérer les liens d'une page web et copier l'adresse url des liens en utilisant Python ?

0 votes

Voici un extrait de code mis à jour qui fait exactement ce que vous demandez en 30 lignes. github.com/mujeebishaque/extract-urls

0 votes

J'ai essayé ceci pour un lien et j'ai obtenu des résultats comme ceci /info-service/downloads/#unserekataloge' . N'est-il pas possible d'obtenir le lien complet accessible ? et pas seulement une partie du sous-lien ? Je veux obtenir les liens vers tous les pdfs disponibles sur le site @MujeebIshaque

211voto

ars Points 35803

Voici un court extrait de l'utilisation de la classe SoupStrainer dans BeautifulSoup :

import httplib2
from bs4 import BeautifulSoup, SoupStrainer

http = httplib2.Http()
status, response = http.request('http://www.nytimes.com')

for link in BeautifulSoup(response, parse_only=SoupStrainer('a')):
    if link.has_attr('href'):
        print(link['href'])

La documentation de BeautifulSoup est en fait assez bonne et couvre un certain nombre de scénarios typiques :

https://www.crummy.com/software/BeautifulSoup/bs4/doc/

Edit : Notez que j'ai utilisé la classe SoupStrainer car elle est un peu plus efficace (en termes de mémoire et de vitesse), si vous savez ce que vous analysez à l'avance.

13 votes

+1, l'utilisation de la passoire à soupe est une excellente idée car elle vous permet d'éviter un grand nombre d'analyses inutiles lorsque vous ne recherchez que les liens.

0 votes

J'ai édité pour ajouter une explication similaire avant de voir le commentaire d'Evan. Merci de l'avoir noté, cependant !

0 votes

Merci, cela résout mon problème, avec cela je termine mon projet merci beaucoup

82voto

Martijn Pieters Points 271458

Par souci d'exhaustivité, la version BeautifulSoup 4, qui utilise également l'encodage fourni par le serveur :

from bs4 import BeautifulSoup
import urllib.request

parser = 'html.parser'  # or 'lxml' (preferred) or 'html5lib', if installed
resp = urllib.request.urlopen("http://www.gpsbasecamp.com/national-parks")
soup = BeautifulSoup(resp, parser, from_encoding=resp.info().get_param('charset'))

for link in soup.find_all('a', href=True):
    print(link['href'])

ou la version Python 2 :

from bs4 import BeautifulSoup
import urllib2

parser = 'html.parser'  # or 'lxml' (preferred) or 'html5lib', if installed
resp = urllib2.urlopen("http://www.gpsbasecamp.com/national-parks")
soup = BeautifulSoup(resp, parser, from_encoding=resp.info().getparam('charset'))

for link in soup.find_all('a', href=True):
    print link['href']

et une version utilisant le requests bibliothèque qui, tel qu'il est écrit, fonctionnera à la fois dans Python 2 et 3 :

from bs4 import BeautifulSoup
from bs4.dammit import EncodingDetector
import requests

parser = 'html.parser'  # or 'lxml' (preferred) or 'html5lib', if installed
resp = requests.get("http://www.gpsbasecamp.com/national-parks")
http_encoding = resp.encoding if 'charset' in resp.headers.get('content-type', '').lower() else None
html_encoding = EncodingDetector.find_declared_encoding(resp.content, is_html=True)
encoding = html_encoding or http_encoding
soup = BeautifulSoup(resp.content, parser, from_encoding=encoding)

for link in soup.find_all('a', href=True):
    print(link['href'])

Le site soup.find_all('a', href=True) l'appel trouve tout <a> qui ont un href Les éléments sans cet attribut sont ignorés.

Le développement de BeautifulSoup 3 a été interrompu en mars 2012 ; les nouveaux projets doivent impérativement utiliser BeautifulSoup 4, toujours.

Notez que vous devez laisser le décodage du HTML à partir des octets à BeautifulSoup . Vous pouvez informer BeautifulSoup du jeu de caractères présent dans les en-têtes de la réponse HTTP pour faciliter le décodage, mais cette information n'est pas disponible. peut être erronée et en conflit avec une <meta> qui se trouve dans le HTML lui-même, c'est pourquoi l'exemple ci-dessus utilise la méthode de la classe interne BeautifulSoup EncodingDetector.find_declared_encoding() pour s'assurer que de tels indices d'encodage intégrés l'emportent sur un serveur mal configuré.

Avec requests le response.encoding La valeur par défaut de cet attribut est Latin-1 si la réponse a un caractère text/* mimetype, même si aucun jeu de caractères n'a été renvoyé. Ceci est cohérent avec les RFCs HTTP mais douloureux lorsqu'il est utilisé avec l'analyse HTML, donc vous devriez ignorer cet attribut lorsqu'aucun fichier charset est défini dans l'en-tête Content-Type.

0 votes

Existe-t-il quelque chose comme StrainedSoup pour bs4 (je n'en ai pas besoin pour l'instant mais je me demande juste, si c'est le cas, vous pourriez vouloir l'ajouter).

0 votes

@AnttiHaapala : SoupStrainer vous voulez dire ? C'est n'a pas disparu, il fait toujours partie du projet. .

0 votes

Y a-t-il une raison pour laquelle ce code ne passe pas "features=" au constructeur de BeautifulSoup ? BeautifulSoup me donne un avertissement concernant l'utilisation d'un analyseur par défaut.

52voto

aehlke Points 4180

D'autres ont recommandé BeautifulSoup, mais il est bien mieux d'utiliser lxml . Malgré son nom, il permet également d'analyser et d'extraire du HTML. Il est beaucoup, beaucoup plus rapide que BeautifulSoup, et il traite même le HTML "cassé" mieux que BeautifulSoup (son titre de gloire). Il possède également une API de compatibilité pour BeautifulSoup si vous ne voulez pas apprendre l'API lxml.

Ian Blicking est d'accord .

Il n'y a plus aucune raison d'utiliser BeautifulSoup, à moins que vous ne soyez sur Google App Engine ou quelque chose d'autre où tout ce qui n'est pas purement Python n'est pas autorisé.

lxml.html prend également en charge les sélecteurs CSS3, de sorte que ce genre de choses est trivial.

Un exemple avec lxml et xpath ressemblerait à ceci :

import urllib
import lxml.html
connection = urllib.urlopen('http://www.nytimes.com')

dom =  lxml.html.fromstring(connection.read())

for link in dom.xpath('//a/@href'): # select the url in href for all a tags(links)
    print link

27 votes

BeautifulSoup 4 utilisera lxml comme analyseur par défaut s'il est installé.

33voto

Andrew Johnson Points 4758
import urllib2
import BeautifulSoup

request = urllib2.Request("http://www.gpsbasecamp.com/national-parks")
response = urllib2.urlopen(request)
soup = BeautifulSoup.BeautifulSoup(response)
for a in soup.findAll('a'):
  if 'national-park' in a['href']:
    print 'found a url with national-park in the link'

1 votes

Cela a résolu un problème que j'avais avec mon code. Merci !

10voto

Sentient07 Points 24

Le code suivant permet de récupérer tous les liens disponibles dans une page web en utilisant urllib2 et BeautifulSoup4 :

import urllib2
from bs4 import BeautifulSoup

url = urllib2.urlopen("http://www.espncricinfo.com/").read()
soup = BeautifulSoup(url)

for line in soup.find_all('a'):
    print(line.get('href'))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X