Подтвердить что ты не робот

Regex, чтобы найти URL-адреса в строке в Python

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

Учитывая следующую строку:

string = "<p>Hello World</p><a href="#" onclick="location.href='http://example.com'; return false;">More Examples</a><a href="#" onclick="location.href='http://example2.com'; return false;">Even More Examples</a>"

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

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

Спасибо!

4b9b3361

Ответ 1

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('http[s]?://(?:[a-zA-Z]|[0-9]|[[email protected]&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', url)

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

Ответ 2

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

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

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

Вместо этого проанализируйте HTML

С этой точки зрения, здесь ваша фактическая заявленная цель: "извлечь URL-адреса внутри якорной метки href". Это разбор HTML. И хотя это очень просто написать регулярное выражение, которое будет захватывать любое значение между <a href= и >...

>>> s = '<p>Hello World</p><a href="#" onclick="location.href='http://example.com'; return false;">More Examples</a><a href="#" onclick="location.href='http://example2.com'; return false;">Even More Examples</a>'
>>> re.findall('<a href="?\'?([^"\'>]*)', s)
['http://example.com', 'http://example2.com']

Это действительно подходит только для одноразовой хакерской штучки. Если в любой момент вы думаете, что можете делать что-то большее, чем очищать URL-адреса для своих собственных случайных целей, вы должны просто взять дополнительные две минуты, чтобы использовать правильный парсер.

Python поставляется со встроенными инструментами, которые делают это довольно просто: вот действительно простой подкласс 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. Короче говоря, это гораздо более мощный и расширяемый способ, чем RE, для извлечения информации из 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']