2017-01-20 4 views
1

私はクロールしたウェブページから特定のURLを抽出する正規表現をjavaに持っています。これらのURLは基本的にjavascriptとスタイルシートで、ページに組み込まれます。私は、正規表現を使用して文書を解析するのではなく、これらを抽出することを選択しました。これは、文書を解析することで、私にとって付加価値がないためです。スピードアップJava正規表現

有効なURL(絶対または相対)を取得するには、私は、次の正規表現を使用します。

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

それは/ endofurl 『「この例では、」(と、URLの』末端との間に何かを取り出します。

例:。 enter image description here

問題は、それはおそらく([^ "」、(] *)の部分)の(つまり、高速ではないということです がすることによってこれをスピードアップする方法はあります例えば、 '/ endofurl'部分を探すようにするまず開始文字の1つに達するまで元に戻りますか?

+0

サンプルURLをいくつか表示できますか? –

+0

URLを抽出するための基本正規表現よりも複雑なメカニズムがあるようですので、各ステップごとにregexを使ってメカニズム/ステップをコードする必要があります。すなわち、ステップ1は最初にendofurlを探し、次にstep 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から次の繰り返しを検索し、String.indexOf(String, int)のオーバーロードをindexOfとします。

+0

いただきありがとうございます。私はmapreduceクラスターでコードを試して、完了したらこのコメントに速度向上を追加します。 – thommie

+0

これは実際に本当にうまくいった、それは2.5時間から4分に行きました。 – thommie

+0

@thommie nice!正規表現は、このような基本的な文字列操作を使用して構築されることを忘れないでくださいだから、あなたが問題を少数の文字列演算を使って表現することができれば、正規表現と同じくらい速いでしょう。君は。速度と読みやすさ/保守性のバランスです。 –

0

たとえば、 '/ endofurl'部分を最初に探して、次に開始文字の1つに達するまで戻っていく方法がありますか?

私が考えることができる本当に恐ろしい方法があります:逆の文字列を検索してください。

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