Обычно гораздо проще и надежнее использовать анализатор HTML, чем регулярное выражение.
Использование стороннего модуля lxml :
import lxml.html as LH
content = '''<html><a href="http://www.not-this-one.com"></a>
<a href="http://www.somewebsite.com"></a><p>other stuff</p><p>sales</p>
</html>
'''
doc = LH.fromstring(content)
for url in doc.xpath('''
//*[contains(text(),"sales")]
/preceding::*[starts-with(@href,"http")][1]/@href'''):
print(url)
выходы
http://www.somewebsite.com
Я считаю, что lxml (и XPath) - это удобный способ выразить, какие элементы я ищу. Однако, если установка стороннего модуля невозможна, вы также можете выполнить эту конкретную работу с помощью HTMLParser из стандартной библиотеки:
import HTMLParser
import contextlib
class MyParser(HTMLParser.HTMLParser):
def __init__(self):
HTMLParser.HTMLParser.__init__(self)
self.last_link = None
def handle_starttag(self, tag, attrs):
attrs = dict(attrs)
if 'href' in attrs:
self.last_link = attrs['href']
content = '''<html><a href="http://www.not-this-one.com"></a>
<a href="http://www.somewebsite.com"></a><p>other stuff</p><p>sales</p>
</html>
'''
idx = content.find('sales')
with contextlib.closing(MyParser()) as parser:
parser.feed(content[:idx])
print(parser.last_link)
Относительно XPath, используемого в решении lxml: XPath имеет следующее значение:
//* # Find all elements
[contains(text(),"sales")] # whose text content contains "sales"
/preceding::* # search the preceding elements
[starts-with(@href,"http")] # such that it has an href attribute that starts with "http"
[1] # select the first such <a> tag only
/@href # return the value of the href attribute