2011-08-10 7 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> 

내가 연속으로 여러 일치 구문 분석하려고하면, 그것은 잘 또한 작동하지만 (내가 가진 동등한 권한 se this)

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가 올바른 것으로 보이고 관련 페이지에서 일치하는 코드가 나오면 정규 표현식이 실패하는 원인이 무엇인지 궁금합니다. 그것과 함께 비웃는 것은 부정적인 lookaheads (페이지 길이와 함께)가 문제를 일으키는 것을 제안하는 것처럼 보이지만, 나는 그들을 어떻게 망쳤는지 잘 모르겠습니다. PHP 5.2.17을 실행하고 있습니다.

+1

및 사용 자체를 제시 수 있을까? –

+1

또한'PCRE_VERSION' 상수를 확인하십시오. 합리적으로 구식이라면, 업데이트 된'libpcre'를 설치하십시오. '(?! ..). +)'어설 션은 아마도 비싸다. regex를 재 작업하거나 preg_replace_callback으로 분리하지 않으려면 phpQuery 또는 QueryPath와 같은 html 툴킷을 사용하여 추출하기 쉽고 (대개는 느리지는 않음) 추출하는 것이 좋습니다. – mario

+0

@mario 내 PCRE_VERSION은 8.02 2010-03-19입니다. 이전 버전 (4 버전이 오래되었습니다)으로 사용할 수 있는지 확실하지 않습니다. 정규식을 다시 작성해야 할 수도 있습니다. 나는 선견지명이 비싸다는 것에 놀랐지 만 당신이 옳다고 생각합니다. 나는 정규식을 재 작업 할 수 없다면 phpQuery와 QueryPath를 살펴볼 것이다. – jela

답변

3

당신은 고전적인 실수 중 하나를 만들었습니다! 정규식을 사용하여 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

그 부정적인 lookaheads는 영리하다,하지만 ... 약간 너무 영리.

그리고 동의하면 이 너무 많아서, 부작용이없는 것으로 나타났습니다.

지금 당장 어떤 게임이 실행되고 있는지 알 수는 없지만 그걸 반복해서 넣어보세요. 탐욕은 항상입니다. ... 당신이 그것을

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

를 작성했습니다 수 있기

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

그것 같이 더 많은 것있다 :

예를 들어이 하나, 확실히 할 필요가 없습니다. 나는 그들을 모두 바꿀거야. 일반적으로

는 정규식 디버깅 당신이 균형 mantainability 기능 사이 을 찾을 때까지 다른 구조를 사용하여, 다른 표현하고 다시하고 다시 다시 문구를 수정을 의미한다.

: <a\s 대신 <a\s+을 사용 하겠지만 조금 더 유연합니다.
약간 유연하게 지불하십시오.

또한 : title=이 콘텐츠를 사용할 수있는 권한이 title\s*=\s*

+0

제목이 흥미로운 경우입니다. 기술적 인 측면에서 보면 앞뒤가 불필요하기 때문입니다. 문제는 때때로 html을 쓰는 사람이 제목에 큰 따옴표를 인코딩하는 데 제대로 실패합니다. 즉, 제목의 끝을 의미하기 위해 큰 따옴표 자체를 신뢰할 수 없음을 의미합니다. 어쨌든 나는 부정적인 lookaheads를 게으른 별들로 대체하고 어떤 일이 일어나는지 보게 될 것입니다. 공백을 확실히 추가하는 것이 옳습니다. – jela

관련 문제