簡體   English   中英

Python正則表達式findall捕獲重復的組

[英]Python regex findall to capture repeated groups

上下文

我正在使用python regex解析某些HTML,因為它們太破損而無法使用更適合那些任務的處理器(例如,選擇器)。 我要解析的HTML的摘錄如下所示:

     <LI><B>First list title</B> Additional info <UL> <LI><I>List element 1</I> additional info </UL> <LI><B>Second list title</B> Additional info <UL> <LI><I>List element 1</I> additional info1 <LI><I>List element 2</I> additional info2 <LI><I>List element 3</I> additional info3 <LI><I>List element 4</I> additional info4 </UL> <!-- many more elements like the ones above --> 

我需要捕獲List標題(和其他信息),並且對於每個標題,它還具有所有嵌套元素及其附加信息。

途徑

import regex as re

re.findall

reg = re.compile("<li><b>(.*)\n\s*<ul>\n(\s*<li>.+\n)+\s*</ul>", re.IGNORECASE)
g_info = re.findall(reg, response.body)

如果在上面的示例中查看info g_info,我們將看到對於具有一個list元素的用戶來說是很好的:

g_info[0] <- ('First list title</B> Additional info', "  <LI><I>List element 1</I> additional info\n")

但是,當有多個子列表元素時,僅獲得最后一個。

g_info[1] <- ('Second list title</B> Additional info', "  <LI><I>List element 4</I> additional info4\n")

我希望它是這樣的:

g_info[1] <- ('Second list title</B> Additional info', "  <LI><I>List element 1</I> additional info1\n", "  <LI><I>List element 2</I> additional info2\n", ...)

研究和捕獲

使用相同的正則表達式,我可以使用.captures函數來捕獲所有元素。 我將對其進行微調,使其適用於以下示例:

reg = re.compile("<li><b>(.*)\n\s*<ul>\n(\s*<li>.+\n){2,}\s*</ul>", re.IGNORECASE)
g_info = re.search(reg, response.body)

但是這種方式(我將使用另一個更簡單的正則表達式進一步解析每個元素以獲得我想要的東西),我只會得到第一個匹配項,而不是所有匹配項。

g_info.captures() <-- '<LI><B>Second list title</B> Additional info\n  <UL>\n  <LI><I>List element 1</I> additional info1\n  <LI><I>List element 2</I> additional info2\n ...'

如果我能以這種格式獲得所有這些信息,那對我來說就足夠了。

re.findall以及其他循環和過濾

我可以使用一個更簡單的正則表達式來獲取所有這些。 然后,我可以進一步檢測出哪個是子元素,哪些不是,因為列表標題始終以粗體標簽開頭,而其他則不是。

reg = re.compile("(\s*<li>.+\n)", re.IGNORECASE)
g_info = re.findall(reg, response.body)

我得到的是這樣的:

g_info[0] <- '\n\n<LI><B>First list title</B> Additional info\n'
g_info[1] <- '\n  <LI><I>List element1</I> additional info\n'
g_info[2] <- '\n\n<LI><B>Second list title</B> Additional info\n'
g_info[3] <- '\n  <LI><I>List element</I> additional info1\n'
g_info[4] <- '  <LI><I>List element2</I> additional info2\n'
g_info[5] <- '  <LI><I>List element3</I> additional info3\n'

解決方案?

我發現的唯一可行的方法是最后一種,恕我直言,這不是很優雅。 您能幫我找到更好的解決方案嗎? 謝謝

import re
pattern = re.compile("(?<=<li><b>).*?(?=</ul>)", re.IGNORECASE | re.DOTALL)
print re.findall(pattern, data)

產量

['First list title</B> Additional info\n  <UL>\n  <LI><I>List element 1</I> additional info\n  ',
 'Second list title</B> Additional info\n  <UL>\n  <LI><I>List element 1</I> additional info1\n  <LI><I>List element 2</I> additional info2\n  <LI><I>List element 3</I> additional info3\n  <LI><I>List element 4</I> additional info4\n  ']

正則表達式解析html不是一個好主意,應盡可能避免RegEx匹配打開的標記(XHTML自包含標記除外)

在走那條路之前,我將重新評估“它們太壞了”,並盡力分析/調試它們,請參閱如何在python中解析格式錯誤的HTML。

暫無
暫無

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

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