我有点害怕问这个因为害怕报复“你不能用正则表达式解析HTML”邪教。为什么re.subn(r'<(script).*?</\1>', '', data, re.DOTALL)
不会删除多行'脚本',而只会删除最后两个单行'脚本'?
谢谢,HC
>>> import re
>>> data = """\
<nothtml>
<head>
<title>Regular Expression HOWTO — Python v2.7.1 documentation</title>
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
VERSION: '2.7.1',
COLLAPSE_MODINDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../_static/jquery.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
"""
>>> print (re.subn(r'<(script).*?</\1>', '', data, re.DOTALL)[0])
<nothtml>
<head>
<title>Regular Expression HOWTO — Python v2.7.1 documentation</title>
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
VERSION: '2.7.1',
COLLAPSE_MODINDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
答案 0 :(得分:6)
不考虑这是否是一个好主意的问题,你的例子的问题是fourth parameter to re.subn
is count
- Python 2.6中没有flags
参数,尽管它是作为第五个引入的Python 2.7中的参数。相反,您可以在正则表达式的末尾添加“(?s)以获得相同的效果:
>>> print (re.subn(r'<(script).*?</\1>(?s)', '', data)[0])
<nothtml>
<head>
<title>Regular Expression HOWTO — Python v2.7.1 documentation</title>
>>>
...或者如果您使用的是Python 2.7,那么这应该可行:
>>> print (re.subn(r'<(script).*?</\1>(?s)', '', 0, data)[0])
...即插入0
作为count
参数。
答案 1 :(得分:4)
为了防止它感兴趣,我想我会添加一个额外的答案,显示使用lxml执行此操作的两种方法,我发现它非常适合解析HTML。 (lxml是one of the alternatives that the author of BeautifulSoup suggests,考虑到后一个库的最新版本的问题。)
添加第一个示例的重点是它非常简单,并且比使用正则表达式删除标记要强大得多。此外,如果您想对文档进行更复杂的处理,或者您正在解析的HTML格式不正确,则您可以使用有效的文档树来编程操作。
此示例基于the HTMLParser example from lxml's documentation:
from lxml import etree
from StringIO import StringIO
broken_html = '''
<html>
<head>
<title>Regular Expression HOWTO — Python v2.7.1 documentation</title>
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
VERSION: '2.7.1',
COLLAPSE_MODINDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../_static/jquery.js"></script>
'''
parser = etree.HTMLParser()
tree = etree.parse(StringIO(broken_html), parser)
for s in tree.xpath('//script'):
s.getparent().remove(s)
print etree.tostring(tree.getroot(), pretty_print=True)
产生此输出:
<html>
<head>
<title>Regular Expression HOWTO — Python v2.7.1 documentation</title>
</head>
</html>
另一方面,因为看起来好像你正试图删除像<script>
这样的笨拙标签,lxml中的Cleaner模块也可能会做你喜欢的其他事情:
from lxml.html.clean import Cleaner
broken_html = '''
<html>
<head>
<title>Regular Expression HOWTO — Python v2.7.1 documentation</title>
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
VERSION: '2.7.1',
COLLAPSE_MODINDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../_static/jquery.js"></script>
'''
cleaner = Cleaner(page_structure=False)
print cleaner.clean_html(broken_html)
...产生输出:
<html><head><title>Regular Expression HOWTO — Python v2.7.1 documentation</title></head></html>
(nb我已将示例中的nothtml
更改为html
- 使用原始方法1正常工作,但将所有内容包装在<html><body>
中,但方法2不起作用因为我现在没有时间弄明白:))
答案 2 :(得分:2)
为了删除html,样式和脚本tages,您可以使用re。
def stripTags(text):
# scripts = re.compile(r'<script.*?/script>')
scripts = re.compile(r'<(script).*?</\1>(?s)')
css = re.compile(r'<style.*?/style>')
tags = re.compile(r'<.*?>')
text = scripts.sub('', text)
text = css.sub('', text)
text = tags.sub('', text)
我可以轻松工作
答案 3 :(得分:1)
简短的回答,是不要那样做。使用Beautiful Soup或elementree来摆脱它们。将数据解析为HTML或XML。正则表达式不起作用,并且是这个问题的错误答案。