2011-08-10 4 views
1

私は、拡張PHPスクリプトに次の正規表現はPHPのpreg_match_all()を使って関数正規表現が失敗するのはなぜですか?

$total_matches = preg_match_all('{ 

     <a\shref=" 
     (?<link>[^"]+) 
     "(?:(?!src=).)+src=" 
     (?<image>[^"]+) 
     (?:(?!designer-name">).)+designer-name"> 
     (?<brand>[^<]+) 
     (?:(?!title=).)+title=" 
     (?<title>((?!">).)+) 
     (?:(?!"price">).)+"price">\$ 
     (?<price>[\d.,]+) 

}xsi',$output,$all_matches,PREG_SET_ORDER); 

この正規表現は、PHPを経由して(以下または小文字を区別しない場合に設定された同じオプションで(regexr.comでパーサーを使用して解析する際に正常に動作するようしています、御馳走行が空白と壊れる):

<a href="http://www.mytheresa.com/us_en/dordogne-120-sandals.html" title= 
    "DORDOGNE 120 PLATEAU SANDALEN" class="product-image"> 
    <img class="image1st" src= "http://mytheresaimages.s3.amazonaws.com/catalog/product/cache/common/product_114114/small_ image/230x260/9df78eab33525d08d6e5fb8d27136e95/P/0/P00027794-DORDOGNE-120-PLATEAU-SANDALEN-STANDARD.jpg" 
    width="230" height="260" 
    alt= "Christian Louboutin - DORDOGNE 120 SANDALS - mytheresa.com GmbH" 
    title= "Christian Louboutin - DORDOGNE 120 SANDALS - mytheresa.com GmbH" /> 
<img class="image2nd" src= "http://mytheresaimages.s3.amazonaws.com/catalog/product/cache/common/product_114114/image/230x260/9df78eab33525d08d6e5fb8d27136e95/P/0/P00027794-DORDOGNE-120-PLATEAU-SANDALEN-DETAIL_2.jpg" 
width="230" height="260" alt= 
"Christian Louboutin - DORDOGNE 120 SANDALS - mytheresa.com GmbH" title= 
"Christian Louboutin - DORDOGNE 120 SANDALS - mytheresa.com GmbH" /> <span class= 
"availability"><strong>available sizes</strong><br /></span></a> 

<div style="margin-left: 2em" class="available-sizes"> 
<h2 class="designer-name">Christian Louboutin</h2> 

<div class="product-buttons"> 
    <div class="product-button"> 
    NEW ARRIVAL 
    </div> 

    <div class="clearer"></div> 
</div> 

<h3 class="product-name"><a href= 
"http://www.mytheresa.com/us_en/dordogne-120-sandals.html" title= 
"DORDOGNE 120 SANDALS">DORDOGNE 120 SANDALS</a></h3> 

<div class="price-box"> 
    <span class="regular-price" id="product-price-114114"><span class= 
    "price">$805.00</span></span> 
</div> 

私は行のいくつかの試合を解析しようとすると、それはまた、正常に動作し、私はこれらの試合から来る全ページを解析しようとすると、しかし、(私が持っています。同行の許可これは)

http://www.mytheresa.com/us_en/new-arrivals/what-s-new-this-week-1.html?limit=12 

正規表現は失敗します(実際には500エラーが発生します)。

ini_set('pcre.backtrack_limit',100000000); 
ini_set('pcre.recursion_limit',100000000); 

を使用してバックトラック制限を引き上げようとしましたが、これで問題は解決しません。私はそれが有効であると思われる正規表現をPHP経由で失敗させる原因となっている間違って何をしているのだろうと疑問に思って、関連するページでコードを一致させます。それに手を加えることは、ページの長さと関連して否定的な先読みが問題を引き起こしていると示唆しているように思われますが、どうやってそれらを取り締まったのか分かりません。私はPHP 5.2.17を実行しています。

+1

としての地位を提示し、そこにコンテンツを使用する許可を持って使用することができますか? –

+1

'PCRE_VERSION'定数もチェックしてください。合理的な時代遅れの場合は、更新された 'libpcre'をインストールしてみてください。 '(?!..)。+)'アサーションはおそらく高価です。正規表現を修正したり、preg_replace_callbackに分割したりしたくない場合は、phpQueryやQueryPathのようなhtmlツールキットを使用して抽出することができます(容易に、またしばしば遅くはない)。 – mario

+0

@mario私のPCRE_VERSIONは8.02 2010-03-19です。古いものとして認定されているかどうかは分かりません(4バージョンが古いです)。私は正規表現を修正する必要があるかもしれないと思う。先読みは高価だと私は驚いていますが、あなたはおそらく正しいと思います。正規表現を書き直すことができない場合は、phpQueryとQueryPathを調べます。 – jela

答えて

3

あなたは古典的な失策の1つを作っています!正規表現を使ってHTMLを解析しないでください!それは正規表現を壊す! (これは、「アジアでの土地戦争に決して関与しない」と「死が行なわれているときはシチリアには絶対に入り込まない」の直後です。あなたがこれを解析するためのSimpleXMLやDOMDOCUMENTを使用する必要があります

$dom = new DomDocument(); 
$dom->loadHTML('http://www.mytheresa.com/us_en/new-arrivals/'. 
       'what-s-new-this-week-1.html?limit=12'); 

$path = new DomXPath($dom); 
// this query is based on the link you provided, not your regex 
$nodes = $path->evaluate('//ul[class="products-grid first odd"]/li'); 
foreach($nodes as $node) 
{ 
    // children 0 = anchor tag you're looking for initially. 
    echo $node->children[0]->getAttribute("href"); 
    // iterate through the other children that way 
} 
+2

新しい "不可解な"バッジが必要です! – Phil

+1

是非考えてみてください。もしあなたが覚えておくべき巨大な遺産のフロントページクルフトを持っていれば、それは確かに考えられます。 – ZJR

+0

@ZJRあなたは、「その言葉、私はあなたがそれが意味すると思うことを意味するとは思わない」と言うあなたの機会を逃した。 – cwallenpoole

1

これらの負の先読みは賢いですが、その後...少しあまりにも巧妙な

私は同意しました、あまりにも多くを使用して、副作用を取得しないでください。

今のところ野生のものは見えませんが、繰り返して.を入れてみてください... 貪欲には常に問題があります。

例えばこれは、確かに不要である:

title=" 
(?<title>((?!">).) 

あなたはより多くのそれのようにあります...

title="(?<title>.*?)"> 

それを書かれている可能性があるので。私はそれらをすべて変えるだろう。一般的に

は、正規表現のデバッグを使用すると、正しいバランス mantainability機能間とを見つけるまで、異なる構築物を使用して、言い換えと何度も何度もと再びそれを言い換えを意味します。

もう1つ<a\sの代わりに<a\s+を使用しますが、少し柔軟性があります。
滞在少しフレキシブル、それは支払う。

またtitle=title\s*=\s*

+0

タイトルの面白いケースです。先読みが余計に技術的に正しいからです。問題は、誰かがhtmlを書いている人が、タイトルの二重引用符を正しくエンコードできないことがあることです。つまり、タイトルの終わりを意味する二重引用符を信頼できません。いずれにしても、私は怠惰な先読みを怠惰な星に置き換え、何が起こるか見ることになるでしょう。あなたは確かにスペースを追加することが正しいです。 – jela

関連する問題