改行をBRタグに置き換える
Posted feedbacks - Python
前のお題の#2759で実装したクラスを継承します。 #2759には下の方にテスト用の式をトップレベルに 書いてあるので適当に処理してください。 置き換えたタグ内の改行も、引用符にくくられていようと 無視して<br/>に置換しています。
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 | from HTMLParser2 import HTMLParser2
class HTMLParser3(HTMLParser2):
def replace(self, s):
return s.replace('&', '&').replace('<', '<').replace('>', '>').replace('\n', '<br/>')
def handle_starttag(self, tag, attrs):
if tag == 'br':
self.buf += '<br/>'
else:
HTMLParser2.handle_starttag(self, tag, attrs)
def handle_data(self, data):
self.buf += data.replace('\n', '<br/>')
def f(s):
h = HTMLParser3()
h.feed(s)
print s
print h.buf
if __name__ == '__main__':
f('''<script foo="<script>alert('bar')</script>">alert('foo')</script>''')
f('''<script foo="<a href='link'>link</a>">alert('foo')</script>''')
f('''<a href='www.g>oogle.com'>link</a>''')
f('''<br>abc\ndef\n<br>''')
|
同じく前回の投稿 #2763 を再利用して。 折角、フィルタ登録型にしたのに、 フィルタ探索関数をクロージャにしてしまったのが裏目にでた。 MyHTMLParserを継承してますが、変更部分は filterメソッド内の find_filter のみです。 今回のお題の追加分は、 fix_br_tag, nl_to_br_in_text 。
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 | # wget http://ja.doukaku.org/comment/2763/download/ -O MyHTMLParser.py
from MyHTMLParser import MyHTMLParser, TEXT,TAG
class MyHTMLParser2(MyHTMLParser):
def filter(self, (state,tag,attrs,text)):
# find_filter = lambda x:x.get((state,tag.lower()), lambda x:x)
def find_filter(filters):
tag_ = tag.lower()
if filters.has_key((state,tag_)):
return filters.get((state,tag_))
return filters.get((state,None), lambda x:x)
tag,attrs = find_filter(self.tag_filters)((tag,attrs))
attrs = find_filter(self.attr_filters)(attrs)
text = find_filter(self.text_filters)(text)
return state,tag,attrs,text
def test(html):
import re
def allow_attrs(*names):
return lambda attrs: [(k,quote(v)) for k,v in attrs if k.lower() in names]
def remove_all_attrs(attrs):
return []
def fix_br_tag((tag,attrs)):
return ('br/',attrs)
def nl_to_br_in_text(text):
return re.sub(text, r"(\r\n|\r|\n)","<br />")
p = MyHTMLParser2()
p.allow_tags += ['a', 'br', 'strong']
p.attr_filters[(TAG,'a')] = allow_attrs('href', 'name')
p.attr_filters[(TAG,'br')] = remove_all_attrs
p.attr_filters[(TAG,'strong')] = remove_all_attrs
p.tag_filters[(TAG,'br')] = fix_br_tag
p.text_filters[(TEXT,None)] = nl_to_br_in_text
p.parse(html)
|
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 | import re
def filter(html):
def repl(m):
beg_slash, tag_name, attrs, _, end_slash = m.groups()
def combine(*names):
s = "<" + beg_slash + tag_name
for m in re.finditer(r"""(\w+)\s*=\s*(["']).+?\2""", attrs, re.S):
if m.group(1).lower() in names:
s += " " + m.group(0)
return s + end_slash + ">"
if tag_name.lower() == "a":
return combine("href", "name")
elif tag_name.lower() == "strong":
return combine()
elif tag_name.lower() == "br": # shortcut
return "<br/>"
else:
return m.group(0).replace("<", "<")
html = re.compile(r"""<(/?)(\w+)((?:\s*\w+\s*=\s*(["']).+?\4)*)\s*(/?)>""", re.S).sub(repl, html)
return re.compile('(<[^>]*>)|(\n)', re.S).sub(lambda m: m.group(1) or "<br/>", html)
def main():
print filter("""<a href='www.google.com'>link</a> <blink>and</blink> <strong onClick='alert("NG")'>click<br>me!</strong>""")
print filter(""" <z foo='<script>alert("Boo")</script>'>""")
print filter("""<a href="foo.com"
name="foo">foo
bar</a>baz
boo""")
if __name__ == '__main__':
main()
|


にしお
#3413()
Rating-2/2=-1.00
また、ユーザの入力注の<br>は<br/>に変換してください。
このお題はperezvonさんの提案を元にした三部作の二問目です。ご協力ありがとうございました。
[ reply ]