Comment puis-je récupérer les liens d'une page Web et copier l'adresse URL des liens en utilisant Python?
141
Comment puis-je récupérer les liens d'une page Web et copier l'adresse URL des liens en utilisant Python?
Voici un court extrait utilisant 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 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 (mémoire et vitesse), si vous savez ce que vous analysez à l'avance.
/usr/local/lib/python2.7/site-packages/bs4/__init__.py:128: UserWarning: The "parseOnlyThese" argument to the BeautifulSoup constructor has been renamed to "parse_only."
has_attr
. Au lieu de cela, je vois qu'il y a quelque chose qui s'appellehas_key
et cela fonctionne.Par souci d'exhaustivité, la version BeautifulSoup 4, utilisant également l'encodage fourni par le serveur:
ou la version Python 2:
et une version utilisant la
requests
bibliothèque , qui, telle qu'elle est écrite, fonctionnera à la fois en Python 2 et 3:le
soup.find_all('a', href=True)
appel trouve tous les<a>
éléments qui ont unhref
attribut; les éléments sans l'attribut sont ignorés.BeautifulSoup 3 a arrêté le développement en mars 2012; les nouveaux projets devraient vraiment utiliser BeautifulSoup 4, toujours.
Notez que vous devez laisser le décodage du HTML d'octets vers BeautifulSoup . Vous pouvez informer BeautifulSoup du jeu de caractères trouvé dans les en-têtes de réponse HTTP pour aider au décodage, mais cela peut être erroné et en conflit avec une
<meta>
information d'en-tête trouvée dans le HTML lui-même, c'est pourquoi ce qui précède utilise la méthode de classe interne de BeautifulSoupEncodingDetector.find_declared_encoding()
pour vous assurer que ces astuces d'encodage intégrées l'emportent sur un serveur mal configuré.Avec
requests
, l'response.encoding
attribut prend par défaut Latin-1 si la réponse a untext/*
type MIME, même si aucun jeu de caractères n'a été renvoyé. Ceci est cohérent avec les RFC HTTP mais pénible lorsqu'il est utilisé avec l'analyse HTML, vous devez donc ignorer cet attribut lorsque nocharset
est défini dans l'en-tête Content-Type.la source
SoupStrainer
tu veux dire? Il n'est allé nulle part, il fait toujours partie du projet .D'autres ont recommandé BeautifulSoup, mais il est préférable d'utiliser lxml . Malgré son nom, il sert également à analyser et à gratter du HTML. C'est beaucoup, beaucoup plus rapide que BeautifulSoup, et il gère même mieux le HTML "cassé" que BeautifulSoup (leur prétention à la renommée). Il dispose également d'une API de compatibilité pour BeautifulSoup si vous ne souhaitez pas apprendre l'API lxml.
Ian Blicking est d'accord .
Il n'y a plus de raison d'utiliser BeautifulSoup, sauf si vous êtes sur Google App Engine ou quelque chose où tout ce qui n'est pas purement Python n'est pas autorisé.
lxml.html supporte également les sélecteurs CSS3, donc ce genre de chose est trivial.
Un exemple avec lxml et xpath ressemblerait à ceci:
la source
lxml
comme analyseur par défaut s'il est installé.la source
Le code suivant permet de récupérer tous les liens disponibles dans une page Web à l'aide de
urllib2
etBeautifulSoup4
:la source
Sous le capot, BeautifulSoup utilise désormais lxml. Requests, lxml & list comprehensions fait un combo tueur.
Dans la liste comp, le "if '//' et 'url.com' not in x" est une méthode simple pour parcourir la liste des URL de navigation des sites 'internes', etc.
la source
juste pour obtenir les liens, sans B.soup et regex:
pour des opérations plus complexes, BSoup est bien entendu toujours préféré.
la source
<a
ethref
? Ditesrel="nofollow"
ouonclick="..."
ou même juste une nouvelle ligne? stackoverflow.com/questions/1732348/…Ce script fait ce que vous recherchez, mais résout également les liens relatifs vers des liens absolus.
la source
Pour trouver tous les liens, nous allons dans cet exemple utiliser le module urllib2 avec le re.module * Une des fonctions les plus puissantes du module re est "re.findall ()". Alors que re.search () est utilisé pour trouver la première correspondance d'un modèle, re.findall () trouve toutes les correspondances et les renvoie sous forme de liste de chaînes, chaque chaîne représentant une correspondance *
la source
Pourquoi ne pas utiliser des expressions régulières:
la source
(r"<a.*?\s*href=\"(.*?)\".*?>(.*?)</a>", page)
signifie? Merci!Les liens peuvent être dans une variété d'attributs afin que vous puissiez passer une liste de ces attributs à sélectionner
par exemple, avec l'attribut src et href (ici, j'utilise l'opérateur commence par ^ pour spécifier que l'une ou l'autre de ces valeurs d'attribut commence par http. Vous pouvez personnaliser cela si nécessaire
Attribut = sélecteurs de valeur
la source
Voici un exemple d' utilisation @ars réponse acceptée et les
BeautifulSoup4
,requests
etwget
modules pour gérer les téléchargements.la source
J'ai trouvé la réponse de @ Blairg23 fonctionnant, après la correction suivante (couvrant le scénario où cela ne fonctionnait pas correctement):
Pour Python 3:
urllib.parse.urljoin
doit être utilisé pour obtenir l'URL complète à la place.la source
Le propre analyseur de BeatifulSoup peut être lent. Il pourrait être plus possible d'utiliser lxml qui est capable d'analyser directement à partir d'une URL (avec certaines limitations mentionnées ci-dessous).
Le code ci-dessus renverra les liens tels quels, et dans la plupart des cas, il s'agirait de liens relatifs ou absolus de la racine du site. Comme mon cas d'utilisation consistait à extraire uniquement un certain type de liens, voici une version qui convertit les liens en URL complètes et qui accepte éventuellement un modèle global comme
*.mp3
. Cependant, il ne gérera pas les points simples et doubles dans les chemins relatifs, mais jusqu'à présent, je n'en avais pas besoin. Si vous avez besoin d'analyser des fragments d'URL contenant../
ou./
alors urlparse.urljoin peut être utile.REMARQUE : L'analyse directe d'url lxml ne gère pas le chargement à partir de
https
et ne fait pas de redirections, c'est pourquoi la version ci-dessous utiliseurllib2
+lxml
.L'utilisation est la suivante:
la source
lxml
ne peut gérer qu'une entrée valide, comment peut-il remplacerBeautifulSoup
?lxml.html
c'est un peu plus indulgent que lelxml.etree
. Si votre entrée n'est pas bien formée, vous pouvez définir explicitement l'analyseur BeautifulSoup: lxml.de/elementsoup.html . Et si vous optez pour BeatifulSoup, BS3 est un meilleur choix.la source
Il peut y avoir de nombreux liens en double avec des liens externes et internes. Pour différencier les deux et obtenir simplement des liens uniques à l'aide d'ensembles:
la source