2015-11-03 76 views
1

我試圖用PHP抓取一系列網頁,抓取標籤和最早標籤之間的所有內容。這是我正在使用的正則表達式:HTML的Catastophic回溯問題

|(?<=div id="body">).*?</div>|s 

這對於我正在查看的大多數頁面來說似乎都工作得很好。但是,它不會爲其他幾個人返回任何東西。我將正則表達式插入到regex101.com測試程序中,它告訴我問題在於災難性的回溯。我試圖消除回顧後的語言,甚至玩弄的東西,如:

|id="body">.*?</div>|s 

然而,問題仍然持續。我已經看了一些關於災難性回溯的其他問題,以及http://www.regular-expressions.info/catastrophic.html文章,但我無法弄清楚如何將這些修復應用到這種特殊情況。

+1

我沒有看到,落入災難性的回溯。你能把我們鏈接到你試過的regex101例子嗎? – Mariano

+0

當然。 https://regex101.com/r/kY8qK0/1 – EAP

+0

爲什麼你需要一個向後看? 'div id =「body」>。*? '作品也一樣。 – sln

回答

0

正則表達式已知會導致帶有大型HTML內容的災難性回溯。在這種情況下,問題無疑是在後退和惰性點匹配的情況下,每當正則表達式引擎向右前進一個符號時,它必須檢查符號是否以指定的子字符串開頭,並且如果它達到足夠的字符產生一場比賽。

這個正則表達式如何工作的一個好主意是看regex101 regex debugger部分。

至於如何分析你的HTML,PHP的DOMDocument和DOMXPath是你最好的朋友:

$html = "<<YOUR_HTML_STRING_HERE>>"; 
$dom = new DOMDocument('1.0', 'UTF-8'); 
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); 
// Above is the DOM initialization from string example, below is parsing 
$xpath = new DOMXPath($dom); 
$divs = $xpath->query('//div[@id="body"]'); // Get all DIV tags with id=body 

foreach($divs as $div) { 
    echo $dom->saveHTML($div); // Echo the HTML, can be added to array 
} 

IDEONE demo

+1

非常感謝!這正是我需要的。 – EAP

+0

@stribizhev你是積極的,這是*災難性的回溯*,因爲問題是不是真的與指數回溯步驟,因爲它會發生在嵌套量詞?注意它會引起相同的錯誤,而不是後視,我相信這是一個普通的* O(n)*超時。 – Mariano

+0

@Mariano:我廣泛使用術語災難性的回溯。超時是由大量的回溯步驟造成的。 –