疑似BUG:Python SGMLParser處理html中的javascript失當

來源:互聯網
上載者:User
疑似BUG:SGMLParser處理html標籤中的javascript時特定情況下失當
庫:Python2.4/2.5的sgmllib庫
牽連庫:Beautiful Soup version 3.0.5以及3.0.3版本

舉例:
html代碼如下定義:    sExceptionHtml = '''<span>出錯的html標籤:</span><div id='error'>
<img src="http://www.onejoo.com/daylife_media/images/articlesid/1.jpg" border="0" 
   onmouseover="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7;
           this.style.cursor='hand';this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}"
   onload="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7;
           this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}"
/>寒!<br /></div>'''

這個img標籤有兩個屬性:onload和onmouseover,裡面都寫的是javascript代碼,並且出現了“>”判斷符號。當讓SGMLParser處理這種html代碼時,它錯誤地解析了。
對於上面的html代碼,會得到如下處理過後的img:
<img src="http://www.onejoo.com/daylife_media/images/articlesid/1.jpg" border="0" onmouseover="if(this.width&gt;screen.width*0.7) {this.resized=true; this.width=screen.width*0.7;
           this.style.cursor='hand';this.alt='Click here to open new window
CTRL+Mouse wheel to zoom in/out';}" />screen.width*0.7) {this.resized=true; this.width=screen.width*0.7;
           this.style.cursor='hand';this.alt='Click here to open new window
CTRL+Mouse wheel to zoom in/out';}"
   onload="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7;
           this.alt='Click here to open new window
CTRL+Mouse wheel to zoom in/out';}"
/>

顯然,onmouseover的東西亂掉了。很有可能就是javascript中的“this.width>screen.width*0.7”中“>”被誤當作html標籤的結束符處理了。
如果確實是這樣,倒也可以理解,只是咱們就受累些,之前提前清除onload屬性和onmouseover屬性吧,省得裡面的javascript幹擾。
    page_content = re.sub('onload=\"\s*[^\"]*\"','',page_content)
    page_content = re.sub('onmouseover=\"\s*[^\"]*\"','',page_content)

牽連影響:並因此影響到了Beautiful Soup對html的解析。

你可以測試如下代碼,可以重現此問題:#coding=utf-8
import sys, os, urllib, re
from sgmllib import SGMLParser
from BeautifulSoup import BeautifulSoup

def replaceHTMLTag(content):
    htmlextractor = html2txt()
    # 調用定義在 SGMLParser 中的 feed 方法,將 HTML 內容放入分析器中。
    htmlextractor.feed(content)
    # 應該 close 您的分析器對象,但出於不同的原因。feed 方法不保證對傳給它的全部 HTML 進行處理,
    # 它可能會對其進行緩衝處理,等待接收更多的內容。一旦沒有更多的內容,應調用 close 來重新整理緩衝區,並且強制所有內容被完全處理。
    htmlextractor.close()
    # 一旦分析器被 close,分析過程也就結束了。htmlextractor.urls 中包含了在 HTML 文檔中所有的連結 URL。

    return htmlextractor.text

# 為了從 HTML 文檔中提取資料,將 SGMLParser 類進行子類化,然後對想要捕捉的標記或實體定義方法。
class html2txt(SGMLParser):
     def __init__(self):
        SGMLParser.__init__(self)
        self._result = []
        self._data_stack = []

     '''
     reset 由 SGMLParser 的 __init__ 方法來調用,也可以在建立一個分析器執行個體時手工來調用。
     所以如果您需要做初始化,在 reset 中去做,而不要在 __init__ 中做。
     這樣當某人重用一個分析器執行個體時,會正確地重新初始化。
     '''
     def reset(self):
         self.text = ''
         self.inbody = True
         SGMLParser.reset(self)
     def handle_data(self,text):
         if self.inbody:
             self.text += text
     def _write(self, d):
        if len(self._data_stack) < 2:
            target = self._result
        else:
            target = self._data_stack[-1]
        if type(d) in (list, tuple):
            target += d
        else:
            target.append(str(d))

     def start_head(self,text):
         self.inbody = False
     def end_head(self):
         self.inbody = True
     def _get_result(self):
        return "".join(self._result).strip()

     result = property(_get_result)


# 應用入口        
if __name__ == '__main__':

    sExceptionHtml = '''<span>出錯的html標籤:</span><div id='error'>
<img src="http://www.onejoo.com/daylife_media/images/articlesid/1.jpg" border="0" 
   onmouseover="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7;
           this.style.cursor='hand';this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}"
   onload="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7;
           this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}"
/>寒!<br /></div>'''
    soup = BeautifulSoup(sExceptionHtml,fromEncoding='gbk')
    body_content = soup.findAll('div',attrs={'id' : re.compile("^error")})
    print '----------------------'
    print body_content[0]
    print '----------------------'
    
    sExceptionHtml = replaceHTMLTag(sExceptionHtml).strip()
    print '----------------------'
    print sExceptionHtml
    print '-----------------------'
    

結論:不是什麼嚴重問題。只是當html代碼中在標籤的屬性中寫javascript時,需要注意到此種特性,如果出現“>”符號,就會導致SGMLParser以及使用SGMLParser的其他庫解析失當。zhengyun 20080115

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.