子串任何类型的 HTML 字符串
Substring any kind of HTML String
我需要将任何类型的 html 代码(字符串)划分为一个标记列表。
例如:
"<abc/><abc/>" #INPUT
["<abc/>", "<abc/>"] #OUTPUT
或
"<abc comfy><room /></abc> <br /> <abc/> " # INPUT
["<abc comfy><room /></abc>", "<br />", "<abc/>"] # OUTPUT
或
"""<meta charset="utf-8" /><title> test123 </title><meta name="test" content="index,follow" /><meta name="description" content="Description" /><link rel="stylesheet" href="../layout/css/default.css" />""" # INPUT
[
'<meta charset="utf-8" />',
"<title> test123 </title>",
'<meta name="test" content="index,follow" />',
'<meta name="description" content="Description123" />',
'<link rel="stylesheet" href="../xx/css/default.css" />',
] # OUTPUT
我尝试做的事情:
def split(html: str) -> List[str]:
if html == "":
return []
delimiter = "/>"
split_name = html.split(" ", maxsplit=1)[0]
name = split_name[1:]
delimited_list = [character + delimiter for character in html.split(delimiter) if character]
rest = html.split(" ", maxsplit=1)[1]
char_delim = html.find("</")
### Help
print(delimited_list)
return delimited_list
我的输出:
['<abc/>', '<abc/>']
['<abc comfy><room />', '</abc> <br />', ' <abc/>', ' />']
['<meta charset="utf-8" />', '<title> test123</title><meta name="test" content="index,follow" />', '<meta name="description" content="Description123" />', '<link rel="stylesheet" href="../xx/css/default.css" />']
所以我尝试在“/>”处拆分,这对第一种情况有效。然后我尝试了几件事。试图识别“名称”,所以html字符串的第一个标识符像“abc”。
你们知道如何继续吗?
谢谢!
问候
尼克
您将需要一个堆栈数据结构并遍历字符串,将开始标签的位置压入堆栈,然后当您遇到结束标签时,我们假设:
它的名字匹配从栈顶位置开始的标签的名字
是自闭标签
我们还维护一个 result
列表来保存已解析的子字符串。
对于1),我们简单地弹出栈顶位置,并将从这个弹出位置切片到结束标记结束的子字符串保存到result
列表中。
对于2),我们不修改栈,只将自闭标签子串保存到result
列表中。
遇到任何标签(打开,关闭,自关闭)后,我们将迭代器(a.k.a。当前位置指针)向前移动该标签的长度(从<
到相应的>
).
如果从迭代器向前切片的 html
字符串不匹配(从头开始)任何标签,那么我们只需将迭代器向前移动一个(我们爬行直到我们可以再次匹配标签)。
这是我的尝试:
import re
def split(html):
if html == "":
return []
openingTagPattern = r"<([a-zA-Z]+)(?:\s[^>]*)*(?<!\/)>"
closingTagPattern = r"<\/([a-zA-Z]+).*?>"
selfClosingTagPattern = r"<([a-zA-Z]+).*?\/>"
result = []
stack = []
i = 0
while i < len(html):
match = re.match(openingTagPattern, html[i:])
if match: # opening tag
stack.append(i) # push position of start of opening tag onto stack
i += len(match[0])
continue
match = re.match(closingTagPattern, html[i:])
if match: # closing tag
i += len(match[0])
result.append(html[stack.pop():i]) # pop position of start of corresponding opening tag from stack
continue
match = re.match(selfClosingTagPattern, html[i:])
if match: # self-closing tag
start = i
i += len(match[0])
result.append(html[start:i])
continue
i+=1 # otherwise crawl until we can match a tag
return result # reached the end of the string
用法:
delimitedList = split("""<meta charset="utf-8" /><title> test123 </title><meta name="test" content="index,follow" /><meta name="description" content="Description" /><link rel="stylesheet" href="../layout/css/default.css" />""")
for item in delimitedList:
print(item)
输出:
<meta charset="utf-8" />
<title> test123 </title>
<meta name="test" content="index,follow" />
<meta name="description" content="Description" />
<link rel="stylesheet" href="../layout/css/default.css" />
参考文献:
openingTagPattern
的灵感来自@Kobi 在这里的回答:
我需要将任何类型的 html 代码(字符串)划分为一个标记列表。 例如:
"<abc/><abc/>" #INPUT
["<abc/>", "<abc/>"] #OUTPUT
或
"<abc comfy><room /></abc> <br /> <abc/> " # INPUT
["<abc comfy><room /></abc>", "<br />", "<abc/>"] # OUTPUT
或
"""<meta charset="utf-8" /><title> test123 </title><meta name="test" content="index,follow" /><meta name="description" content="Description" /><link rel="stylesheet" href="../layout/css/default.css" />""" # INPUT
[
'<meta charset="utf-8" />',
"<title> test123 </title>",
'<meta name="test" content="index,follow" />',
'<meta name="description" content="Description123" />',
'<link rel="stylesheet" href="../xx/css/default.css" />',
] # OUTPUT
我尝试做的事情:
def split(html: str) -> List[str]:
if html == "":
return []
delimiter = "/>"
split_name = html.split(" ", maxsplit=1)[0]
name = split_name[1:]
delimited_list = [character + delimiter for character in html.split(delimiter) if character]
rest = html.split(" ", maxsplit=1)[1]
char_delim = html.find("</")
### Help
print(delimited_list)
return delimited_list
我的输出:
['<abc/>', '<abc/>']
['<abc comfy><room />', '</abc> <br />', ' <abc/>', ' />']
['<meta charset="utf-8" />', '<title> test123</title><meta name="test" content="index,follow" />', '<meta name="description" content="Description123" />', '<link rel="stylesheet" href="../xx/css/default.css" />']
所以我尝试在“/>”处拆分,这对第一种情况有效。然后我尝试了几件事。试图识别“名称”,所以html字符串的第一个标识符像“abc”。
你们知道如何继续吗?
谢谢!
问候 尼克
您将需要一个堆栈数据结构并遍历字符串,将开始标签的位置压入堆栈,然后当您遇到结束标签时,我们假设:
它的名字匹配从栈顶位置开始的标签的名字
是自闭标签
我们还维护一个 result
列表来保存已解析的子字符串。
对于1),我们简单地弹出栈顶位置,并将从这个弹出位置切片到结束标记结束的子字符串保存到result
列表中。
对于2),我们不修改栈,只将自闭标签子串保存到result
列表中。
遇到任何标签(打开,关闭,自关闭)后,我们将迭代器(a.k.a。当前位置指针)向前移动该标签的长度(从<
到相应的>
).
如果从迭代器向前切片的 html
字符串不匹配(从头开始)任何标签,那么我们只需将迭代器向前移动一个(我们爬行直到我们可以再次匹配标签)。
这是我的尝试:
import re
def split(html):
if html == "":
return []
openingTagPattern = r"<([a-zA-Z]+)(?:\s[^>]*)*(?<!\/)>"
closingTagPattern = r"<\/([a-zA-Z]+).*?>"
selfClosingTagPattern = r"<([a-zA-Z]+).*?\/>"
result = []
stack = []
i = 0
while i < len(html):
match = re.match(openingTagPattern, html[i:])
if match: # opening tag
stack.append(i) # push position of start of opening tag onto stack
i += len(match[0])
continue
match = re.match(closingTagPattern, html[i:])
if match: # closing tag
i += len(match[0])
result.append(html[stack.pop():i]) # pop position of start of corresponding opening tag from stack
continue
match = re.match(selfClosingTagPattern, html[i:])
if match: # self-closing tag
start = i
i += len(match[0])
result.append(html[start:i])
continue
i+=1 # otherwise crawl until we can match a tag
return result # reached the end of the string
用法:
delimitedList = split("""<meta charset="utf-8" /><title> test123 </title><meta name="test" content="index,follow" /><meta name="description" content="Description" /><link rel="stylesheet" href="../layout/css/default.css" />""")
for item in delimitedList:
print(item)
输出:
<meta charset="utf-8" />
<title> test123 </title>
<meta name="test" content="index,follow" />
<meta name="description" content="Description" />
<link rel="stylesheet" href="../layout/css/default.css" />
参考文献:
openingTagPattern
的灵感来自@Kobi 在这里的回答: