-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathhtmlnode.py
More file actions
112 lines (82 loc) · 3.63 KB
/
Copy pathhtmlnode.py
File metadata and controls
112 lines (82 loc) · 3.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import re
import httplib
class HTMLNode(object):
_tmpText = ''
def __init__(self, tag = '', id = '', name = '', attr = None, nodes = None, html = ''):
self.attributes = {}
self.daughters = []
if tag:
self.tag = tag
if attr:
for key, value in attr.items():
self.attributes[key] = value
if id: self.attributes['id'] = id
if name: self.attributes['name'] = name
if nodes:
for node in nodes:
self.daughters.append(node)
elif html:
matches = re.match('<\\s*(\\w+)([^>]*)>', html, re.MULTILINE)
if matches:
# if html starts with a flag, that becomes the root node
self.tag = matches.group(1).lower()
attrlist = re.findall('(\\w+)\\s*=\\s*(\'[^\']*\'|"[^"]*"|[^ ]*)', matches.group(2))
for attr in attrlist:
self.attributes[attr[0].lower()] = attr[1].strip('\'"')
isSingle = matches.group(2) and matches.group(2)[-1] == '/'
HTMLNode._tmpText = html[len(matches.group(0)):].lstrip()
if isSingle:
return
else:
# html starts with a normal string
self.tag = ''
text = re.split('<[^>]*>', html, 1, re.MULTILINE)[0]
self.attributes['text'] = text
HTMLNode._tmpText = html[len(text):].lstrip()
while HTMLNode._tmpText:
if HTMLNode._tmpText.startswith('</'):
if not self.tag:
# we are in a daughter text tag -> return
return
closeMatch = re.match('</\\s*%s\\s*>' % self.tag, HTMLNode._tmpText, re.IGNORECASE)
if not closeMatch:
raise RuntimeError('Non-matching close tag: ' + HTMLNode._tmpText[:20])
HTMLNode._tmpText = HTMLNode._tmpText[len(closeMatch.group(0)):].lstrip()
return
else:
self.daughters.append(HTMLNode(html = HTMLNode._tmpText))
else:
raise RuntimeError('HTMLNode needs tag or html')
def addDaughter(self, tag = '', id = '', name = '', attr = None, nodes = None, html = ''):
newnode = HTMLNode(tag = tag, id = id, name = name, attr = attr, nodes = nodes, html = '')
self.daughters.append(newnode)
return newnode
def addText(self, text):
self.daughters.append(HTMLNode(html = text.strip()))
def getDaughtersByTag(self, tag):
return filter(lambda n : n.tag == tag, self.daughters)
def findDaughtersByTag(self, tag):
result = []
if self.tag == tag: result.append(self)
for node in self.daughters:
try:
result += node.findDaughtersByTag(tag)
except AttributeError:
pass
return result
def generateHTML(self, indent = 0):
html = ' ' * indent
if self.tag:
html += '<' + self.tag
for key, value in self.attributes.items():
html += ' ' + key + '="' + value + '"'
if len(self.daughters) == 0:
html += ' />\n'
else:
html += '>\n'
for node in self.daughters:
html += node.generateHTML(indent + 2)
html += ' ' * indent + '</' + self.tag + '>\n'
else:
html += self.attributes['text'] + '\n'
return html