web-dev-qa-db-fra.com

Regex pour extraire les URL de l'attribut href en HTML avec Python

Duplicate possible:
Quelle est la meilleure expression régulière pour vérifier si une chaîne est une URL valide?

Considérant une chaîne comme suit:

string = "<p>Hello World</p><a href="http://example.com">More Examples</a><a href="http://example2.com">Even More Examples</a>"

Comment pourrais-je, avec Python, extraire les URL, à l'intérieur du href de la balise anchor? Quelque chose comme:

>>> url = getURLs(string)
>>> url
['http://example.com', 'http://example2.com']

Merci!

79
user825286
import re

url = '<p>Hello World</p><a href="http://example.com">More Examples</a><a href="http://example2.com">Even More Examples</a>'

urls = re.findall('https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+', url)

>>> print urls
['http://example.com', 'http://example2.com']
172
JohnJohnGa

La meilleure réponse est ...

N'utilisez pas de regex

L'expression dans le réponse acceptée manque de nombreux cas. Entre autres choses , les URL peuvent contenir des caractères unicode . La regex que vous voulez est ici , et après l'avoir examinée, vous pouvez en conclure que vous ne le voulez pas vraiment après tout. La version la plus correcte est dix mille caractères .

Certes, si vous débutiez avec du texte brut, non structuré contenant une multitude d'URL, vous pourriez avoir besoin de cette expression rationnelle longue de dix mille caractères. Mais si votre entrée est structurée, utilisez la structure . Votre objectif déclaré est "d'extraire l'URL, à l'intérieur du href de la balise d'ancrage". Pourquoi utiliser une expression rationnelle longue de dix mille caractères lorsque vous pouvez faire quelque chose de beaucoup plus simple?

Analyser le HTML à la place

Pour de nombreuses tâches, utiliser Beautiful Soup sera beaucoup plus rapide et facile à utiliser:

>>> from bs4 import BeautifulSoup as Soup
>>> html = Soup(s, 'html.parser')           # Soup(s, 'lxml') if lxml is installed
>>> [a['href'] for a in html.find_all('a')]
['http://example.com', 'http://example2.com']

Si vous préférez ne pas utiliser d'outils externes, vous pouvez également utiliser directement la propre bibliothèque d'analyse HTML intégrée de Python. Voici une sous-classe très simple de HTMLParser qui fait exactement ce que vous voulez:

from html.parser import HTMLParser

class MyParser(HTMLParser):
    def __init__(self, output_list=None):
        HTMLParser.__init__(self)
        if output_list is None:
            self.output_list = []
        else:
            self.output_list = output_list
    def handle_starttag(self, tag, attrs):
        if tag == 'a':
            self.output_list.append(dict(attrs).get('href'))

Tester:

>>> p = MyParser()
>>> p.feed(s)
>>> p.output_list
['http://example.com', 'http://example2.com']

Vous pouvez même créer une nouvelle méthode qui accepte une chaîne, appelle feed et renvoie output_list. Il s'agit d'un moyen beaucoup plus puissant et extensible que les expressions régulières pour extraire des informations à partir de HTML.

53
senderle