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']
Спасибо!
Ответы
Ответ 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']