簡體   English   中英

用於去除腳本標記的Python正則表達式

[英]Python regular expression to strip script tags

我有點害怕問這個因為害怕報復“你無法用正則表達式解析HTML”邪教。 為什么re.subn(r'<(script).*?</\\1>', '', data, re.DOTALL)不會刪除多行'腳本',而只刪除最后的兩個單行'腳本',請?

謝謝,HC

>>> import re
>>> data = """\
<nothtml> 
  <head> 
    <title>Regular Expression HOWTO &mdash; 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 &mdash; 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> 

撇開一般來說這是否是一個好主意的問題,你的例子的問題是re.subn第四個參數是count - Python 2.6中沒有flags參數,盡管它是作為Python 2.7中的第五個參數引入的。 相反,你可以在正則表達式的末尾添加`(?s)以獲得相同的效果:

>>> print (re.subn(r'<(script).*?</\1>(?s)', '', data)[0])

<nothtml> 
  <head> 
    <title>Regular Expression HOWTO &mdash; Python v2.7.1 documentation</title> 




>>>

...或者如果您使用的是Python 2.7,這應該可行:

>>> print (re.subn(r'<(script).*?</\1>(?s)', '', 0, data)[0])

...即插入0作為count參數。

為了防止它感興趣,我想我會添加一個額外的答案,顯示使用lxml執行此操作的兩種方法,我發現它非常適合解析HTML。 (lxml是BeautifulSoup的作者建議的替代方案之一,考慮到后一個庫的最新版本的問題。)

添加第一個示例的重點是它非常簡單,並且比使用正則表達式刪除標記要強大得多。 此外,如果要對文檔執行任何更復雜的處理,或者如果要解析的HTML格式不正確,則可以使用可以通過編程方式操作的有效文檔樹。

刪除所有腳本標記

此示例基於lxml文檔中的HTMLParser示例

from lxml import etree
from StringIO import StringIO

broken_html = '''
<html> 
  <head> 
    <title>Regular Expression HOWTO &mdash; 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 &#8212; Python v2.7.1 documentation</title>
  </head>
</html>

使用lxml的Cleaner模塊

另一方面,因為看起來好像你正試圖刪除像<script>這樣的笨拙標簽,lxml中的Cleaner模塊也會做你喜歡的其他事情:

from lxml.html.clean import Cleaner

broken_html = '''
<html> 
  <head> 
    <title>Regular Expression HOWTO &mdash; 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>

(我已經在你的例子nothtml更改為html - 使用原始方法,方法1工作正常,但將所有內容包裝在<html><body> ,但方法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)

我可以輕松工作

簡短的回答是,不要這樣做。 使用美麗的湯或元素來擺脫它們。 將數據解析為HTML或XML。 正則表達式不起作用,是這個問題的錯誤答案。

暫無
暫無

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

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