簡體   English   中英

提取正則表達式匹配的一部分

[英]Extract part of a regex match

我想要一個正則表達式來從 HTML 頁面中提取標題。 目前我有這個:

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

是否有正則表達式可以僅提取 <title> 的內容,因此我不必刪除標簽?

在 regexp 中使用( )並在 python 中使用group(1)來檢索捕獲的字符串(如果re.search沒有找到結果,它將返回None ,所以不要直接使用group() ):

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

if title_search:
    title = title_search.group(1)

請注意,從Python 3.8開始,並引入了賦值表達式 (PEP 572) ( :=運算符),可以通過在 if 條件中直接捕獲匹配結果作為變量並重用來改進Krzysztof Krasoń 的解決方案它在條件的身體:

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

嘗試使用捕獲組:

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

我可以向您推薦美麗的湯。 Soup 是一個非常好的庫,可以解析所有的 html 文檔。

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

嘗試:

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

我認為這應該足夠了:

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

...假設您的文本 (HTML) 位於名為“text”的變量中。

這也假設沒有其他 HTML 標記可以合法地嵌入到 HTML TITLE 標記中,並且沒有辦法在這樣的容器/塊中合法地嵌入任何其他 < 字符。

然而...

不要在 Python 中使用正則表達式進行 HTML 解析。 使用 HTML 解析器! (除非您要編寫一個完整的解析器,當各種 HTML、SGML 和 XML 解析器已經在標准庫中時,這將是一項額外的和冗余的工作)。

如果您正在處理“真實世界”標簽湯HTML(通常不符合任何 SGML/XML 驗證器),請使用BeautifulSoup包。 它不在標准庫中(目前),但為此目的被廣泛推薦。

另一種選擇是: lxml ...它是為正確結構化(符合標准)的HTML編寫的。 但它可以選擇使用 BeautifulSoup 作為解析器: ElementSoup

提供的代碼片段不能處理我建議的Exceptions

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

如果未找到模式或第一個匹配項,則默認情況下返回一個空字符串。

Krzysztof Krasoń 目前投票最多的答案以<title>a</title><title>b</title>失敗。 此外,它會忽略跨越行邊界的標題標簽,例如,出於行長的原因。 最后,它以<title >a</title>失敗(這是有效的 HTML: XML/HTML 標記內的空白)。

因此,我提出以下改進:

import re

def search_title(html):
    m = re.search(r"<title\s*>(.*?)</title\s*>", html, re.IGNORECASE | re.DOTALL)
    return m.group(1) if m else None

測試用例:

print(search_title("<title   >with spaces in tags</title >"))
print(search_title("<title\n>with newline in tags</title\n>"))
print(search_title("<title>first of two titles</title><title>second title</title>"))
print(search_title("<title>with newline\n in title</title\n>"))

輸出:

with spaces in tags
with newline in tags
first of two titles
with newline
  in title

最終,我和其他人一起推薦了一個 HTML 解析器 - 不僅,而且處理 HTML 標記的非標准使用。

我需要一些東西來匹配package-0.0.1 (name, version) 但想要拒絕無效版本,例如0.0.010

請參閱regex101示例。

import re

RE_IDENTIFIER = re.compile(r'^([a-z]+)-((?:(?:0|[1-9](?:[0-9]+)?)\.){2}(?:0|[1-9](?:[0-9]+)?))$')

example = 'hello-0.0.1'

if match := RE_IDENTIFIER.search(example):
    name, version = match.groups()
    print(f'Name:     {name}')
    print(f'Version:  {version}')
else:
    raise ValueError(f'Invalid identifier {example}')

輸出:

Name:     hello
Version:  0.0.1

為什么沒有人建議使用前瞻和后瞻,有什么特別的原因嗎? 我來到這里試圖做同樣的事情, (?<=<title>).+(?=<\/title>)效果很好。 它只會匹配括號之間的內容,因此您不必執行整個組的操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM