Wyodrębnij część dopasowania wyrażenia regularnego


130

Chcę, aby wyrażenie regularne wyodrębniło tytuł ze strony HTML. Obecnie mam to:

title = re.search('<title>.*</title>', html, re.IGNORECASE).group()
if title:
    title = title.replace('<title>', '').replace('</title>', '') 

Czy istnieje wyrażenie regularne do wyodrębniania tylko zawartości <title>, aby nie musieć usuwać tagów?


5
wow, nie mogę uwierzyć we wszystkie odpowiedzi wzywające do przeanalizowania całej strony HTML tylko w celu wyodrębnienia prostego tytułu. Co za przesada!
hoju

4
Tytuł pytania mówi wszystko - podany przykład to HTML, ale ogólny problem jest ... ogólny.
Phil

Odpowiedzi:


208

Użyj ( )w regexp i group(1)pythonie, aby pobrać przechwycony ciąg ( re.searchzwróci, Nonejeśli nie znajdzie wyniku, więc nie używaj group()bezpośrednio ):

title_search = re.search('<title>(.*)</title>', html, re.IGNORECASE)

if title_search:
    title = title_search.group(1)

1
Jeśli nic nie robisz, gdy nie zostanie znaleziony żaden tytuł, dlaczego byłoby źle używać bezpośrednio group ()? (i tak możesz złapać wyjątek)
tonfa

1
tak, ale większość ludzi zapomina o wyjątkach i jest naprawdę zdziwiona, kiedy widzą je na runtime :)
Krzysztof Krasoń

Nie zapomnij biec, import rebo inaczej dostanieszNameError: name 're' is not defined
Powers

16

Zwróć uwagę, że rozpoczynając Python 3.8i wprowadzając wyrażenia przypisania (PEP 572) ( :=operator), można nieco ulepszyć rozwiązanie Krzysztofa Krasonia, przechwytując wynik dopasowania bezpośrednio w warunku if jako zmienną i ponownie wykorzystując go w treści warunku :

# pattern = '<title>(.*)</title>'
# text = '<title>hello</title>'
if match := re.search(pattern, text, re.IGNORECASE):
  title = match.group(1)
# hello

6

Spróbuj użyć grup przechwytywania:

title = re.search('<title>(.*)</title>', html, re.IGNORECASE).group(1)


4

Mogę polecić Beautiful Soup. Zupa to bardzo dobra biblioteka do analizowania całego dokumentu HTML.

soup = BeatifulSoup(html_doc)
titleName = soup.title.name

Dodam, że beautifulsoup parsuje też niekompletny html i to jest naprawdę fajne.
koniec

3

Próbować:

title = re.search('<title>(.*)</title>', html, re.IGNORECASE).group(1)

Jeśli naprawdę chcesz użyć REGEX do analizy HTML, nie uruchamiaj .group () bezpośrednio po dopasowaniu, ponieważ może zwrócić None.
iElectric

Powinieneś użyć .*?tego w przypadku, gdy </title>w dokumencie jest wiele (mało prawdopodobne, ale nigdy nie wiadomo).
tonfa,

@iElectric: możesz spróbować z wyjątkiem bloku, jeśli naprawdę chcesz, prawda?
tonfa,

3

Podane fragmenty kodu nie radzą sobie z Exceptions propozycją

getattr(re.search(r"<title>(.*)</title>", s, re.IGNORECASE), 'groups', lambda:[u""])()[0]

Zwraca to domyślnie pusty ciąg, jeśli wzorzec nie został znaleziony lub pierwszy pasujący.


1

Myślę, że to powinno wystarczyć:

#!python
import re
pattern = re.compile(r'<title>([^<]*)</title>', re.MULTILINE|re.IGNORECASE)
pattern.search(text)

... zakładając, że Twój tekst (HTML) znajduje się w zmiennej o nazwie „tekst”.

Zakłada się również, że nie ma innych tagów HTML, które można legalnie osadzić w tagu HTML TITLE i nie ma możliwości legalnego osadzenia żadnego innego znaku <w takim kontenerze / bloku.

Jednak ...

Nie używaj wyrażeń regularnych do analizowania kodu HTML w Pythonie. Użyj parsera HTML! (Chyba że masz zamiar napisać pełny parser, co byłoby dodatkową pracą, gdy różne parsery HTML, SGML i XML są już w standardowych bibliotekach.

Jeśli obsługujesz „rzeczywisty” kod HTML zupy tagów (który często nie jest zgodny z jakimkolwiek walidatorem SGML / XML), użyj pakietu BeautifulSoup . Nie ma go (jeszcze) w standardowych bibliotekach, ale jest szeroko zalecany do tego celu.

Inną opcją jest: lxml ..., który jest napisany dla odpowiednio skonstruowanego (zgodnego ze standardami) HTML. Ale ma opcję powrotu do używania BeautifulSoup jako parsera: ElementSoup .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.