2011-12-24 61 views
1

考慮以下HTML輸入:Python類HTMLParser的錯誤給予解析錯誤

<html> 
<head> 
<script> 
function open_tools(tool_div) 
{ 
    document.getElementById("tool1").innerHTML = "<a href='javascript:void(0);' onclick=\"javascript:clos_tools('""');\"><img src='menu.gif' border='0' /></a>"; 
    document.getElementById("tool").innerHTML = "<a href='javascript:void(0);' onclick=\"javascript:open_tools('""');\"><img src='plus.gif' border='0' /></a>"; 
} 
</script> 
</head> 
<body /> 
</html> 

爲了快速測試,假設你在 'test.html中' Python的外殼轉儲這個網站的數據,

>>> f = open('test.html', 'r') 
>>> data = f.read() 
>>> from HTMLParser import HTMLParser 
>>> p = HTMLParser() 
>>> p.feed(data) 

Burrrppp ......與以下錯誤

File "lib\HTMLParser.py", line 155, in goahead 
    k = self.parse_starttag(i) File "lib\HTMLParser.py", line 235, in parse_starttag 
    endpos = self.check_for_whole_start_tag(i) File "lib\HTMLParser.py", line 319, in check_for_whole_start_tag 
    self.error("malformed start tag") File "lib\HTMLParser.py", line 115, in error 
    raise HTMLParseError(message, self.getpos()) HTMLParseError: malformed start tag, at line 7, column 88 

我與這個錯誤過去混淆6個小時。這是我在裏面發現的HTMLParser.py代碼:

解析時,遇到腳本標記時,它設置cdata = true。 之後,它使用interesting_cdata= re.compile(r'<(/|\Z)')正則表達式來找出script標籤的結束[內goahead()]

不幸的是,現在看來,這是找到腳本標籤的末尾</a>function open_tools而不是在</script>第一條語句。然後它在功能的第二行中出現毛刺。

我不知道如何解決這個問題,並想到HTMLParser中的錯誤令人不安。誰能幫忙?

注:我是一個Python愛好者及以上與Python 2.6測試(窗口)

編輯:是的,它的工作原理與BeautifulSoup。但我有興趣知道正則表達式是否被破壞(以及如何修復)以及HTMLParser類的其他問題。在圖書館代碼的第一步卡住是令人沮喪的。關於PHP文檔的好處是能夠在官方文檔頁面上發表評論。同樣在msdn上也被支持。

+1

不知道這一點的錯誤 - 但你試過用BeautifulSoup? – BeRecursive 2011-12-24 21:13:12

+0

我可以完全解析片段可以用Python 2.7.2的'HTMLParser'。 – 2011-12-24 21:23:08

+2

@larsmans:我已經在2.5-2.7,3.0-3.3上試過它,它只能在3.3(cpython-e0df57330b83)上運行,例如3.1 http://ideone.com/x4qB3 – jfs 2011-12-25 04:46:47

回答

4

it seems it is finding end of script tag in </a> of first statement

是的,這是正確的根據HTML4標準這樣做。

在HTML < 5(以及SGML從這種行爲是遺傳),像<script><style>一個CDATA-元件由</(ETAGO)序列結束。該序列不是匹配結束標記的一部分是錯誤的。

因此,爲了驗證爲HTML4必須確保沒有</序列中包含的腳本塊。 (如果它是你自己的代碼,最簡單的方法就是將它們寫成JS字符串文字轉義,如<\/\x3C/。但是如果它是你自己的代碼,那麼你需要使用DOM方法來代替,以避免所有轉義問題。)

在HTML5此被改變,以便只有匹配的結束標籤結束CDATA塊。這更符合傳統的瀏覽器行爲。如果您使用HTML5解析器(例如html5lib),則可以。

+0

D'oh,html4 !!我下載頁面並將html數據提供給解析器,以便我可以提供JS的替代品。但是現在我已經搬到了BeautifulSoup,它的行爲是正確的。希望您的評論可以在HTMLParser的python官方文檔中提及。 – 2011-12-25 18:49:00

2

HTMLParser模塊docs的標題說明了一切:

HTMLParser — Simple HTML and XHTML parser

其中 「簡單」 確實意味着簡單

如果你想做任何嚴肅的HTML解析,使用BeautifulSouplxml

編輯

要回答關於錯誤的具體問題:

這似乎與在issue 13358報告的錯誤的,對此修復應包括在Python 2.7的下一個版本和3.2。

(我還是我的上述聲明的立場,雖然;-)

+1

[html5lib](http://code.google.com/p/html5lib/)也。它可以與lxml進行互操作。 – 2011-12-24 21:52:00

+0

@ekhumoro:d我覺得我的HTML片段也足夠簡單。我會很高興知道爲什麼這個正則表達式被破壞了(而且,它是真的打破了,還是有一些其他的錯誤,例如在HTML代碼?)。 – 2011-12-25 09:38:57

+0

@ vivek.m。請看我更新的答案。 – ekhumoro 2011-12-25 15:33:26