Regex для извлечения URL-адресов из атрибута href в HTML с помощью Python

Возможный дубликат:
Какое регулярное выражение лучше всего проверить, является ли строка допустимым URL-адресом?

Рассматривая строку следующим образом:

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

Как я мог, с помощью Python, извлечь URL внутри href тега привязки? Что-то вроде:

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

Спасибо!

2 ответа

Решение
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']

Лучший ответ...

Не используйте регулярные выражения

Выражение в принятом ответе пропускает многие случаи. Помимо прочего, URL-адреса могут содержать символы Юникода. Регулярное выражение, которое вы хотите, здесь, и, взглянув на него, вы можете заключить, что вы действительно не хотите его в конце концов. Самая правильная версия длиной в десять тысяч символов.

По общему признанию, если вы начинали с простого, неструктурированного текста с кучей URL-адресов, то вам может понадобиться это регулярное выражение длиной в десять тысяч символов. Но если ваш вклад структурирован, используйте структуру. Ваша заявленная цель состоит в том, чтобы "извлечь url, внутри href тега привязки". Зачем использовать регулярное выражение длиной в десять тысяч символов, если вы можете сделать что-то гораздо более простое?

Разбор HTML вместо

Для многих задач использование Beautiful Soup будет намного быстрее и проще в использовании:

>>> 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']

Если вы предпочитаете не использовать внешние инструменты, вы также можете напрямую использовать собственную встроенную библиотеку Python для разбора HTML. Вот действительно простой подкласс HTMLParser это именно то, что вы хотите:

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'))

Тестовое задание:

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

Вы могли бы даже создать новый метод, который принимает строку, вызывает feed и возвращает output_list, Это гораздо более мощный и расширяемый способ извлечения информации из html, чем регулярные выражения.

Другие вопросы по тегам