python
  • regex
  • python-3.x
  • 2016-10-22 25 views 0 likes 
    0

    我試圖解析某個文檔中的HTML img標籤,特別是我想要查找圖像的所有src,alttitle屬性。屬性總是以相同的順序,但是titlealt是可選的,它們可能不存在。Python:正則表達式中的可選組

    我試過在我的正則表達式中使組(?:title="(.*?)")?可選,但它不起作用。任何幫助,將不勝感激。

    example = '<img class="alignnone wp-image-4170 size-full" title="example_title" src="http://www.example.com/wp-content/uploads/2016/07/example.jpg" alt="example_alt" width="300" height="430" />' 
    re.search(r'(?:title="(.*?)")?.*?src="(.*?)".*?(?:alt="(.*?)")?', example).groups() 
    >>> (None, 'http://www.example.com/wp-content/uploads/2016/07/example.jpg', None) 
    

    預期的結果將是:

    ('example_title', 'http://www.example.com/wp-content/uploads/2016/07/example.jpg', 'example_alt') 
    
    +1

    你是否正在使用正則表達式來學習練習?因爲應該避免使用正則表達式解析HTML。你應該使用適當的解析器。 – idjaw

    +0

    你期望的結果是什麼? – BrenBarn

    +0

    @idjaw,我同意,但在我的情況下,使用類似beautifulsoup模塊會是一個矯枉過正。我只想解析一些簡短的博客文章。 –

    回答

    4

    可以拿到冠軍通過移動第一.*?你的第一個非捕獲組內的匹配:

    >>> re.search(r'(?:title="(.*?)".*?)?src="(.*?)".*?(?:alt="(.*?)")?', example).groups() 
    ('example_title', 
    'http://www.example.com/wp-content/uploads/2016/07/example.jpg', 
    None) 
    

    這個問題你正則表達式是它包含。*在一個可選組之後。這意味着,在字符串的開頭,正則表達式被「允許」與可選組不匹配(因爲它是可選的),而是繼續匹配它後面的內容。因爲它後面是.*?,它會匹配任何東西,這總是成功的,它不需要匹配你的標題組。它只是使用.*?來匹配從字符串開頭到「src」的所有內容,然後匹配「src」。在非捕獲組內部移動.*?將強制它不匹配「任何東西」,除非它首先匹配標題;那麼它只會匹配「src」,如果它沒有找到標題第一的話,那麼它就會一直提升其搜索位置。

    正如在評論中提到的那樣,以這種方式解析HTML並不是一個好主意。你的問題其實就是爲什麼。當你寫下(?:title="(.*?)")?.*?時,你可能會想到的是「可選標題後跟任何東西」,但問題是「任何東西」也可以包含標題,所以它的實際含義是「字符串和任何東西,或任何東西(包括我們將忽略的標題)「。當您嘗試將諸如title=這樣的特定匹配與像.*這樣的通用匹配結合使用時,您試圖捕獲的內容可能會被.*弄糊塗,而不是被更具體的組捕獲。另外,你的代碼假設title,src和alt總是按照這個順序出現,但是它們可能以任何順序出現,在這種情況下,你的regex將無法正確捕獲它們。

    +0

    非常感謝!你說得對,移動。*?在非捕獲組內真正幫助。另外,謝謝你的深入解釋,我想我必須學習很多關於正則表達式:) –

    相關問題