2013-02-19 6 views
1

정규 표현식을 작성하여 HTML 소스의 URL 목록 hrefanchor 텍스트를 추출하려고합니다. anchor 텍스트는 모든 값이 될 수 있습니다. 이 HTML을 정규식으로 구문 분석하려면 어떻게해야합니까?

<div class="links"><a rel="nofollow" target="_blank" href="http://url1.com" class="get-all">URL1</a><a rel="nofollow" target="_blank" href="http://url2.com" class="get-all">This is Url-2</a><a rel="nofollow" target="_blank" href="http://url3.com" class="get-all">This is Url-3</a><a rel="nofollow" target="_blank" href="http://url4.com" class="get-all">Sweet URL 4</a></div> 

나는 다음과 같은 정규 표현식을 시도했지만 그것은 </a> 태그 앞에 모든 것을 잡고 실패 이후 작동하지 않습니다 :

하는 HTML 부분은 다음과 같이 간다.

preg_match_('/<a rel="nofollow" target="_blank" href="(.*)" class="see-all">(.*)<\/a>/', $source , $website_array); 

필요한 데이터를 추출하는 데 사용할 수있는 정규식은 무엇입니까?

+1

왜 그냥 HTML을 구문 분석 할 수 있습니까? – Blender

+8

http : // stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags # answer-1732454 정규 표현식을 사용하여 HTML을 평가하지 말고 구문 분석하십시오. 가장 간단한 대답은 다음과 같습니다. HTML은 정규 언어가 아닙니다. – KingCrunch

+0

얘들 아, 나는 "HTML을 파싱하기 위해 정규식을 사용하지 말라"는 것을 얻는다. 그러나 이것은 정말로 간단한 문제이다. Regexp를 사용하지 않기 위해서 모든 코드를 변경하고 싶지 않습니다. –

답변

6

알아야 할 점은 표현식이 욕심이 많으므로 첫 번째 앵커의 시작과 마지막 앵커의 끝이 일치 할 가능성이 높습니다. /U 수정은 해결됩니다 : pcre.backtrack_limit이 ungreedy 모드에 적용

preg_match('/<a rel="nofollow" target="_blank" href="(.*)" class="see-all">(.*)<\/a>/U', $source , $website_array); 

하는 것으로. 더 나은 성능을 줄 수도 예견 세트를 사용

:

preg_match('/<a rel="nofollow" target="_blank" href="([^"]*)" class="see-all">([^<]*)<\/a>/', $source , $website_array); 

이 앵커 자체 내부 태그에 문제가있을 것이다. ,

$d = new DOMDocument; 
$d->loadHTML($source); 
$xp = new DOMXPath($d); 
foreach ($xp->query('//a[@class="see-all"][@rel="nofollow"][@target="_blank"]') as $anchor) { 
    $href = $anchor->getAttribute('href'); 
    $text = $anchor->nodeValue; 
} 

Demo

이 행복하게 다른 순서로 속성을 처리하고 당신에게 더 안쪽 조회 할 수있는 기능을 제공합니다 : 상기 제한으로

, 나는 심각하게 HTML 파서를 사용하는 것이 좋습니다 것입니다 등

+0

/U 수정자는 정확하게 내가 찾고있는 것입니다! –

+1

@PeterLur 마일리지가 다를 수 있습니다 :) 또한 백 트랙 제한 설정에 대한 내 의견을 참조하십시오. –

2

시도

preg_match_all('/<a[^>]+href="([^"]+)"[^>]*>([^>]+)<\/a>/is', $source , $website_array); 

모든 링크와 일치하며 정보가있는 배열을 반환합니다. 참고 :

[^은 "] -

1

정규식 HTML을 구문 분석하는 것은 일반적으로 좋은 생각이지만, 그것은 일부의 경우에 사용할 수 있습니다 (I 더 나은 솔루션을있는 DOMDocument 클래스에보고 제안)를 제외한 모든 문자와 일치" 어디에서 압축을 풀려고하는지에 대한 아주 구체적인 생각을 갖고 있으며, 모든 경우에 변수 텍스트가 실제로 정규 표현식을 손상시키지 않을 것이라고 확신 할 수 있습니다.

사건에 대한

, 당신은 시도 할 수 있습니다 :

$pattern = '#<a rel="nofollow" target="_blank" href="(.*)" class="get-all">(.*)</a>#U'; 
preg_match_all($pattern, $source, $website_array); 

주에게 마지막에 ungreedy 수정 (U)를. 가능한 한 가장 작은 일치 항목 만 일치시키는 것이 매우 중요합니다.

0

또는 당신은 이런 식으로 작업을 수행 할 수 있습니다

<?php 
$html = <<<HTML 
<div class="links"><a rel="nofollow" target="_blank" href="http://url1.com" class="get-all">URL1</a><a rel="nofollow" target="_blank" href="http://url2.com" class="get-all">This is Url-2</a><a rel="nofollow" target="_blank" href="http://url3.com" class="get-all">This is Url-3</a><a rel="nofollow" target="_blank" href="http://url4.com" class="get-all">Sweet URL 4</a></div> 
HTML; 


$xml = new DOMDocument(); 
@$xml->loadHTML($html); 

$links=array(); 
$i=0; 
//Get all divs 
foreach($xml->getElementsByTagName('div') as $divs) { 
    //if this div has a class="links" 
    if($divs->getAttribute('class')=='links'){ 
     //loop through this div 
     foreach($xml->getElementsByTagName('a') as $a){ 
      //if this a tag dose not have a class="get-all" continue to next 
      if($a->getAttribute('class')!='get-all') 
      continue; 

      //Assign values to the links array 
      $links[$i]['href']=$a->getAttribute('href'); 
      $links[$i]['value']=$a->nodeValue; 
      $i++; 
     } 

    } 
} 

print_r($links); 
/* 
Array 
(
    [0] => Array 
     (
      [href] => http://url1.com 
      [value] => URL1 
     ) 

    [1] => Array 
     (
      [href] => http://url2.com 
      [value] => This is Url-2 
     ) 

    [2] => Array 
     (
      [href] => http://url3.com 
      [value] => This is Url-3 
     ) 

    [3] => Array 
     (
      [href] => http://url4.com 
      [value] => Sweet URL 4 
     ) 

) 
*/ 
?> 
관련 문제