2017-04-26 84 views
1

我有一個代碼可以抓取一百萬個網站並檢測其主頁上的聯繫信息。防止正則表達式中的災難性回溯

對於某些原因,當我運行的代碼,它卡住和status=done

我已經運行的代碼數次爬行約60K的請求後,不會繼續,我標誌着我的DB的網站網址,但它得到約有60k個請求。

它不卡在某個網站上。

下面是正則表達式我使用

emails = re.findall('[\w\.-][email protected][\w-]+\.[\w\.-]+', lc_body) 
    mobiles = re.findall(r"(\(?(?<!\d)\d{3}\)?-? *\d{3}-? *-?\d{4})(?!\d)|(?<!\d)(\+\d{11})(?!\d)", lc_body) 
    abns = re.findall('[a][-\.\s]??[b][-\.\s]??[n][-\:\.\s]?[\:\.\s]?(\d+[\s\-\.]?\d+[\s\-\.]?\d+[\s\-\.]?\d+)', lc_body) 

    licences = re.findall(r"(Licence|Lic|License|Licence)\s*(\w*)(\s*|\s*#\s*|\s*.\s*|\s*-\s*|\s*:\s+)(\d+)", lc_body, re.IGNORECASE) 

我的想法是licences的正則表達式是造成問題,我如何簡化呢?我怎樣才能刪除回溯?

我想查找所有可能的許可證號碼。

它可以是License No: 2543License: 2543License # 2543License #2543License# 2543和許多其他的組合爲好。

+1

最佳做法是在交替組中使用不同於相同位置的替代方案。請提供導致問題的字符串。 –

+0

'(許可證| Lic |許可證|許可證]'=>'(許可證| Lic |許可證)'對於初學者:) –

+1

@ Jean-FrançoisFabre:不,'Lic(?:en [cs] e)?'。這個問題是由第三組產生的,''(\ s * | \ s *。\ s * | \ s * - \ s * | \ s *:\ s +)' - all替代品以'\ s *'開頭。它應該匹配什麼? –

回答

1

該問題是由第三組引起的:(\s*|\s*#\s*|\s*.\s*|\s*-\s*|\s*:\s+) - 所有替代方案均以\s*開頭。這會導致大量冗餘回溯,因爲這些替代方法可以匹配字符串中的相同位置。 最佳做法是在交替組中使用不同於相同位置的替代方案。

現在,看着你需要匹配字符串,我建議使用

Lic(?:en[cs]e)?(?:\W*No:)?\W*\d+ 

regex demo

使圖案更加具體和線性,擺脫許多alternations越好,使用optional non-capturing groups和字符類。

詳細

  • Lic(?:en[cs]e)? - Lic接着用1點或0的出現(該(?:...)?是一個可選的non-capturing group因爲?量詞匹配1點或0的出現的量化子模式)的enceense(字符類[sc]匹配sc,並且比(s|c)更有效
  • (?:\W*No:)? - 匹配的1點或0的出現0+非字字符(具有\W*)非捕獲組,隨後用No:
  • \W*
  • \d+ - 1或多個數字。