2017-01-20 68 views
1

我在java中有一個正則表達式來從我爬過的網頁中提取某些url。這些網址基本上都是JavaScript和樣式表,它們被納入到網頁中。我選擇使用正則表達式來提取這些文件,而不是解析文檔,因爲這應該更容易,解析文檔對我來說沒有任何附加價值。加速Java正則表達式

要得到有效的URL(絕對或相對)我用下面的正則表達式:

([^"',\(]*)/endofurl 

它提取之間的任何東西「」,(和URL的結束,在這個例子中‘/ endofurl’。

例子: enter image description here

的問題是,它不是快速(可能是因爲([^「」,(*)部分) 有沒有辦法通過加快這。例如讓它尋找'/ endofurl'部分首先,然後返回,直到它到達其中一個開始字符?

+0

你能告訴我們一些示例網址嗎? –

+0

這聽起來像你有一個更復雜的機制比提取網址的基本正則表達式,所以你可能需要使用正則表達式爲每一步編碼你的機制/步驟。即第1步首先查找endofurl,然後第2步等。 – abstractx1

+4

我認爲在這裏單獨使用正則表達式是錯誤的工具。您應該使用XML/HTML解析器來抓取感興趣的標籤/節點。在此之後,您可以在每個隔離標籤上使用正則表達式來驗證URL。 –

回答

1

有沒有必要使用這個正則表達式。

找到/endofurl

int endOfUrl = s.indexOf("/endofurl"); 

然後(在檢查該endOfUrl != -1)找到的",(第一次出現之前:

int start = Math.max( // Fictional version of Math.max which takes 3 inputs. 
    s.lastIndexOf('"', endOfUrl), 
    s.lastIndexOf(',', endOfUrl), 
    s.lastIndexOf('(', endOfUrl)); 

然後(在檢查該start != -1)提取物字符串:

String substring = s.substring(start + 1, endOfUrl + "/endofurl".length()); 

然後重複從endOfUrl + 1找到下一個出現,使用indexOfString.indexOf(String, int)過載。

+0

感謝您的意見,我會在我的mapreduce集羣上嘗試您的代碼,並在完成後爲此評論添加速度改進。 – thommie

+0

這實際上工作非常好,從2.5小時到4分鐘。 – thommie

+0

@ thommie不錯!請記住,正則表達式使用像這樣的基本字符串操作來構建;所以如果你可以使用幾個字符串操作來表達你的問題,你至少會像正則表達式那樣表達你的問題,並且可能會更快(因爲你找到了),因爲你沒有剩下的正則表達式引擎的其他東西,呃,幫助您。這是速度與可讀性/可維護性的平衡。 –

0

有沒有一種方法可以加快速度,例如先查找'/ endofurl'部分,然後返回,直到達到其中一個起始字符?

有一種真正可怕的方式,我可以想到:搜索字符串反向。

Pattern pattern = Pattern.compile("lrufodne/[^"',(]*"); 
Matcher matcher = pattern.matcher(new StringBuilder(s).reverse().toString()); 
while (matcher.find()) { 
    System.out.println(new StringBuilder(matcher.group()).reverse().toString()); 
} 

雖然,我不會推薦這個。使用基本字符串操作更容易。


另一種方法是拆就你不想要的字符字符串,並查找包含/endofurl字符串:

for (String part : s.split("[^\"',(]")) { 
    int endOfUrl = part.indexOf("/endofurl"); 
    if (endOfUrl != -1) { 
    System.out.println(part.substring(0, endOfUrl + "/endofurl".length()); 
    } 
} 

但同樣,我會去更基本的字符串操作:你並不需要在這裏構造所有的附加字符串和數組。

0

或者你可以在正則表達式改爲

"([\w.]*/)*endofurl 

,並使用完全匹配。這從366步驟降低到36,並且還提供了(顯着的?)加速。

See it here at regex101