2012-03-27 4 views
1

DOMDocumentDOMXPath에 필요한 HTML 데이터가 있습니다.XPath 쿼리 및 HTML - 앵커 내 특정 HREF 찾기 태그

그러나 특정 <a> 태그에서 href 값에 액세스하여 검색해야합니다.

  1. href 포함 : some-site.vendor.com/jobs/[#idnumber]/job (즉 some-site.vendor.com/jobs/23094/job를)

  2. href하지 포함 some-site.vendor.com/jobs/search?search=pr2

  3. href하지 포함 some-site.vendor.com/jobs/intro

  4. href하지 포함 다음은 기준입니다 : www.someothersite.com/

  5. href하지 포함 media.someothersite.com/

  6. href하지 포함 javascript:void(0)

이 (유사) 쿼리 중 하나가 4-6 제외한 모든 것을 가져 - 그건 좋은 일 :

$joblinks = $xpath->query('//a[@href[contains(., "https://some-site.vendor.com/jobs/")]]');  
$joblinks = $xpath->query('//a[@href[contains(., "job")]]'); 

그러나 궁극적으로 # 1과 같은 href를 포함하는 모든 앵커 태그에 액세스해야합니다. d 실제 href 값을 변수/배열에 할당합니다. 여기에 내가 뭘하는지입니다 :이 정말 날 때리고있다

$payload = fetchRemoteData(SPEC_SOURCE_URL); 

// suppress warning(s) due to malformed markup 
libxml_use_internal_errors(true); 

// load the fetched contents 
$dom = new DOMDocument(); 
$dom->preserveWhiteSpace = false; 
$dom->loadHTML($payload); 

// parse and cache the required data elements 
$xpath = new DOMXPath($dom); 

//$joblinks = $xpath->query('//a[@href[contains(., "some-site.vendor.com/jobs/")]]'); 
$joblinks = $xpath->query('//a[@href[contains(., "job")]]'); 
foreach($joblinks as $joblink) { 
    var_dump(trim($joblink->nodeValue)); // dump hrefs here! 
} 
echo "\n"; 

- 내가 가까이 있어요하지만 난 그냥 제대로 쿼리를 조정할 및/또는 실제 HREF 값에 액세스 할 수없는 것. 내가이 질문에 어떤 프로토콜을 따르지 않았다면 나의 가장 겸손한 사과 ...

ANY/ALL 도움이 크게 감사드립니다! 고맙습니다.

+0

이 필요한 HREF 값을 필터링하는 것입니다 전적으로 XPath 쿼리를 사용합니까? 나는 그것이 가능하다고 확신하지만, 머리가 아프다 (전형적인 XPath). 아마도'$ xpath-> query()'를 사용하여 넓은 패턴 (예 :'href = "https://some-site.vendor.com/jobs/")과 일치하는 노드리스트를 얻은 다음, 몇 줄의 PHP를 사용하여 각 노드의 href 값을 더 자세히 조사하십시오. –

+0

XPath 1.0보다는 XPath 1.0이 확실히 불필요하게 장황하게 만듭니다 ...하지만 그것이 우리가 가지고있는 전부입니다. ['registerphpfunctions'] (http://php.net/manual/en/domxpath.registerphpfunctions.php)와의 정규식 매치를 할 수있는 함수를 만들 것입니다. – Wrikken

답변

1

여기서는 전적으로 xpath을 사용하지 않습니다. 우선 화이트리스트와 블랙리스트가 있습니다. 당신이 원하는 것이 무엇인지는 분명하지 않으므로 시간이 지남에 따라 바뀔 수 있다고 가정합니다.

그러면 할 수있는 일은 먼저 문제의 모든 href 속성을 선택하고 노드를 반환하는 것입니다. 즉 XPath는이 매우 좋은거야, 그래서 XPath를 사용하자 :

if (!$links = $xpath->query('//a/@href')) { 
    throw new Exception('XPath query failed.'); 
} 

이제 $links의 일반적인 DOMNodeList을 가지고 우리가 사람들을 선택로는 0 개 이상의 DOMAttr 요소가 포함되어 있습니다. 이것들은 이제 당신이 찾고있는 필터링을 필요로합니다.

그래서 일치시키고 싶은 기준이 있습니다. 당신은 그것이 어떻게 작동해야하는지 상세하지는 않지만 매우 구체적이지 않습니다. 긍정적 인 성냥과 부정적 성냥이 있습니다. 그러나 두 경우 모두 당신은 어떤 일이 일어나지 않아야하는지 말하지 않습니다.그래서 여기에 바로 가기를 수행

function is_valid_href($href) { 

    // do whatever you see fit ... 

    return true or false; 
} 

그래서 href 지금 유효한지 여부를 말하는 문제가하십시오 "href" 문자열 기준 (들)과 일치하는 경우 당신은 자신에게 하나 true 또는 false을 반환하는 함수를 작성 해결되었습니다. 가장 좋은 점은 나중에 변경할 수 있습니다.

그래서 필요한 것은 모든 링크를 정규화 된 절대 형식으로 얻는 것입니다. 이것은 더 많은 데이터 처리를 참조 의미 : URL 정상화의 다른 유형에 대한 자세한 내용은

.

그래서 href 정규화, 기본 해상도 및 유효성 검사를 캡슐화하는 다른 함수를 만듭니다. href를 잘못 경우, 그냥 그렇지 않으면 정규화 된 HREF, null를 반환

function normalize_href($href, $base) { 

    // do whatever is needed ... 

    return null or "href string"; 
} 

는 검증이 혜택을 누릴 수 있도록 내 경우에는 내가 심지어 HREF Net_URL2 인스턴스를 만들의 함께이를 넣어 보자.

당연히 이것을 클로저 또는 일부 클래스로 마무리하면 더 멋진 인터페이스가됩니다. 또한 당신은뿐만 아니라 XPath 식 매개 변수하게 생각 couold :

// get all href 
if (!$links = $xpath->query('//a/@href')) { 
    throw new Exception('XPath query failed.'); 
} 

// set a base URL 
$base = 'https://stackoverflow.com/questions/9894956/xpath-query-html-find-specific-hrefs-within-anchor-tags'; 

/** 
* @return bool 
*/ 
function is_valid_href($href) {  
    ... 
} 

/** 
* @return href 
*/ 
function normalize_href($href, $base) { 
    ... 
} 

$joblinks = array(); 
foreach ($links as $attr) { 
    $href = normalize_href($attr->nodeValue, $base); 
    if (is_valid_href($href)) { 
     $joblinks[] = $href; 
    } 
} 

// your result is in: 
var_dump($joblinks); 

내가 본 웹 사이트의 예를 실행했습니다, 그 결과는 다음과 같습니다

array(122) { 
    [0]=> 
    object(Net_URL2)#129 (8) { 
    ["_options":"Net_URL2":private]=> 
    array(5) { 
     ["strict"]=> 
     bool(true) 
     ["use_brackets"]=> 
     bool(true) 
     ["encode_keys"]=> 
     bool(true) 
     ["input_separator"]=> 
     string(1) "&" 
     ["output_separator"]=> 
     string(1) "&" 
    } 
    ["_scheme":"Net_URL2":private]=> 
    string(4) "http" 
    ["_userinfo":"Net_URL2":private]=> 
    bool(false) 
    ["_host":"Net_URL2":private]=> 
    string(17) "stackexchange.com" 
    ["_port":"Net_URL2":private]=> 
    bool(false) 
    ["_path":"Net_URL2":private]=> 
    string(1) "/" 
    ["_query":"Net_URL2":private]=> 
    bool(false) 
    ["_fragment":"Net_URL2":private]=> 
    bool(false) 
    } 
    [1]=> 

    ... 

    [121]=> 
    object(Net_URL2)#250 (8) { 
    ["_options":"Net_URL2":private]=> 
    array(5) { 
     ["strict"]=> 
     bool(true) 
     ["use_brackets"]=> 
     bool(true) 
     ["encode_keys"]=> 
     bool(true) 
     ["input_separator"]=> 
     string(1) "&" 
     ["output_separator"]=> 
     string(1) "&" 
    } 
    ["_scheme":"Net_URL2":private]=> 
    string(4) "http" 
    ["_userinfo":"Net_URL2":private]=> 
    bool(false) 
    ["_host":"Net_URL2":private]=> 
    string(22) "blog.stackoverflow.com" 
    ["_port":"Net_URL2":private]=> 
    bool(false) 
    ["_path":"Net_URL2":private]=> 
    string(30) "/2009/06/attribution-required/" 
    ["_query":"Net_URL2":private]=> 
    bool(false) 
    ["_fragment":"Net_URL2":private]=> 
    bool(false) 
    } 
} 
관련 문제