2010-08-21 9 views
1

Analyser les codes HTML/JS pour obtenir des informations en utilisant PHP.Comment analyser une page HTML en utilisant PHP?

www.asos.com/Asos/Little-Asos-Union-Jack-T-Shirt/Prod/pgeproduct.aspx?iid=1273626

Jetez un oeil à cette page, il est un magasin de vêtements pour enfants . C'est l'un de leurs articles et je tiens à souligner la section de taille. Ce que nous devons faire ici est d'obtenir toutes les tailles pour cet article et de vérifier si les tailles sont disponibles ou non. En ce moment toutes les tailles pour ces articles sont:

3-4 years 
4-5 years 
5-6 years 
7-8 years 

Comment pouvez-vous dire si les tailles sont disponibles ou non?

Maintenant, jetez un oeil à cette page d'abord et vérifier à nouveau les tailles:

www.asos.com/Ralph-Lauren/Ralph-Lauren-Long-Sleeve-Big-Horse-Stripe-Rugby-Top/ ? Prod/pgeproduct.aspx IID = 1111751

Cet article a les dimensions suivantes:

12 months 
18 months - Not Available 
24 months 

Comme vous pouvez le voir 18 mois taille ne sont pas disponibles, il est indiqué par le texte « non disponible » à côté la taille.

Ce que nous devons faire est aller à la page d'un article, obtenir les tailles et vérifier la disponibilité de chaque taille. Comment puis-je faire cela en PHP?

EDIT:

Ajout d'un code de travail et un nouveau problème à résoudre.

Code de travail mais il a besoin de plus de travail:

<?php 

function getProductVariations($url) { 

    //Use CURL to get the raw HTML for the page 
    $ch = curl_init(); 
    curl_setopt_array($ch, 
    array(
     CURLOPT_RETURNTRANSFER=>true, 
     CURLOPT_HEADER => false, 
     CURLOPT_URL => $url 
    ) 
); 
    $raw_html = curl_exec($ch); 

    //If we get an invalid response back from the server fail 
    if ($raw_html===false) { 
    throw new Exception(curl_error($ch)); 
    } 

    curl_close($ch); 

    //Find the variation JS declarations and extract them 
    $raw_variations = preg_match_all("/arrSzeCol_ctl00_ContentMainPage_ctlSeparateProduct\[[0-9]+\].*Array\((.*)\);/",$raw_html,$raw_matches); 

    //We are done with the Raw HTML now 
    unset($raw_html); 

    //Check that we got some results back 
    if (is_array($raw_matches) && isset($raw_matches[1]) && sizeof($raw_matches[1])==$raw_variations && $raw_variations>0) { 

    //This is where the matches will go 
    $matches = array(); 

    //Go through the results of the bracketed expression and convert them to a PHP assoc array 
    foreach($raw_matches[1] as $match) { 

     //As they are declared in javascript we can use json_decode to process them nicely, they just need wrapping 
     $proc=json_decode("[$match]"); 

     //Label the fields as best we can 
     $proc2=array(
     "variation_id"=>$proc[0], 
     "size_desc"=>$proc[1], 
     "colour_desc"=>$proc[2], 
     "available"=>(trim(strtolower($proc[3]))=="true"), 
     "unknown_col1"=>$proc[4], 
     "price"=>$proc[5], 
     "unknown_col2"=>$proc[6],  /*Always seems to be zero*/ 
     "currency"=>$proc[7], 
     "unknown_col3"=>$proc[8], 
     "unknown_col4"=>$proc[9],  /*Negative price*/ 
     "unknown_col5"=>$proc[10],  /*Always seems to be zero*/ 
     "unknown_col6"=>$proc[11]  /*Always seems to be zero*/ 
    ); 

     //Push the processed variation onto the results array 
     $matches[$proc[0]]=$proc2; 

     //We are done with our proc2 array now (proc will be unset by the foreach loop) 
     unset($proc2); 
    } 

    //Return the matches we have found 
    return $matches; 

    } else { 
    throw new Exception("Unable to find any product variations"); 

    } 
} 


//EXAMPLE USAGE 
try { 
    $variations = getProductVariations("http://www.asos.com/Asos/Prod/pgeproduct.aspx?iid=803846"); 

    //Do something more useful here 
    print_r($variations); 


} catch(Exception $e) { 
    echo "Error: " . $e->getMessage(); 
} 

?> 

Le code ci-dessus fonctionne, mais il y a un problème lorsque le produit doit d'abord sélectionner une couleur avant que les tailles sont affichées.

Comme celui-ci:

http://www.asos.com/Little-Joules/Little-Joules-Stewart-Venus-Fly-Trap-T-Shirt/Prod/pgeproduct.aspx?iid=1171006

Toute idée comment s'y prendre?

+0

Je viens de découvrir que l'option pour la taille de sélection est peuplée par AJAX. Comme vous pouvez le voir, ceci est la sélection de taille DIV. Les informations qui peuplent cette DIV proviennent apparemment d'une interaction AJAX avec un script backend. Les mots "non disponible" ne sont pas dans le HTML, mais ils sont clairement rendus sur l'écran lorsque vous ouvrez le contrôle de formulaire SELECT. Donc, ils sont mis dans le DOM d'une autre manière. Est-ce que fopen et file_get_contents fonctionneront toujours ici? – GoDesigner

Répondre

3

SOLUTION:

function curl($url){ 
     $ch = curl_init(); 
     curl_setopt($ch, CURLOPT_URL,$url); 
     curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); 
     return curl_exec($ch); 
     curl_close ($ch); 
    } 

$html = curl('http://www.asos.com/pgeproduct.aspx?iid=1111751'); 

preg_match_all('/arrSzeCol_ctl00_ContentMainPage_ctlSeparateProduct\[(.*?)\] \= new Array\((.*?),\"(.*?)\",\"(.*?)\",\"(.*?)\"/is',$html,$bingo); 

echo print_r($bingo); 

Lien: http://debconf11.com/stackoverflow.php

Vous êtes sur votre propre maintenant :)

EDIT2:

Ok, nous sommes proches de solution ...

<script type="text/javascript">var arrSzeCol_ctl00_ContentMainPage_ctlSeparateProduct = new Array; 
arrSzeCol_ctl00_ContentMainPage_ctlSeparateProduct[0] = new Array(1164,"12 months","SailingOrange","True","","59.00","0.00","£","","-59.00","0.00","0"); 
arrSzeCol_ctl00_ContentMainPage_ctlSeparateProduct[1] = new Array(1165,"18 months","SailingOrange","False","","59.00","0.00","£","","-59.00","0.00","0"); 
arrSzeCol_ctl00_ContentMainPage_ctlSeparateProduct[2] = new Array(1167,"24 months","SailingOrange","True","","59.00","0.00","£","","-59.00","0.00","0"); 
</script> 

Il n'est pas chargé via ajax, à la place le tableau est dans la variable javascript. Vous pouvez analyser cela avec PHP, vous pouvez clairement voir que 18 mois est un faux, ce qui signifie qu'il n'est pas disponible.

EDIT:

Cette taille sont chargés via javascript, donc vous ne pouvez pas les analyser, car ils ne sont pas là. Je peux extraire seulement cela ...

<select name="drpdwnSize" id="ctl00_ContentMainPage_ctlSeparateProduct_drpdwnSize" onchange="drpdwnSizeChange(this, 'ctl00_ContentMainPage_ctlSeparateProduct', arrSzeCol_ctl00_ContentMainPage_ctlSeparateProduct);"> 
<option value="-1">Select Size</option> 
</select> 

Vous pouvez renifler JS pour vérifier si vous pouvez charger des formats basés sur ID produit.


Tout d'abord vous avez besoin: http://simplehtmldom.sourceforge.net/ Oublier file_get_contents() est ~ 5 plus lent que cURL.

Vous analysez ensuite ce morceau de code (html avec id ctl00_ContentMainPage_ctlSeparateProduct_drpdwnSize)

 <select id="ctl00_ContentMainPage_ctlSeparateProduct_drpdwnSize" name="ctl00$ContentMainPage$ctlSeparateProduct$drpdwnSize" onchange="drpdwnSizeChange(this, 'ctl00_ContentMainPage_ctlSeparateProduct', arrSzeCol_ctl00_ContentMainPage_ctlSeparateProduct);"> 

     <option value="-1">Select Size</option><option value="1164">12 months</option><option value="1165">18 months - Not Available</option><option value="1167">24 months</option></select> 

Vous pouvez ensuite utiliser preg_match(), explode(), str_replace() et d'autres pour filtrer les valeurs que vous voulez. Je peux l'écrire mais je n'ai pas le temps en ce moment :)

+0

Suggestions d'alternatives tierces qui utilisent réellement DOM au lieu de String Analysis: [phpQuery] (http://code.google.com/p/phpquery/), [Zend_Dom] (http://framework.zend.com/manual/ en/zend.dom.html), [QueryPath] (http://querypath.org/) et [FluentDom] (http://www.fluentdom.org). – Gordon

+0

J'ai aussi découvert que la sélection des tailles est peuplée par javascript. Je suis plus perdu maintenant sur ce qu'il faut faire, qu'est-ce qu'un sniff JS? – GoDesigner

+0

Pour vérifier à partir de quel script (côté serveur) sont les tailles chargées, j'ai essayé de trouver, mais c'est juste un gâchis. Il a des tonnes de JS, dont je ne suis pas sûr que ce soit nécessaire. Veuillez patienter ... –

1

La manière la plus simple d'extraire le contenu d'une URL est de faire appel à des wrappers fopen et d'utiliser simplement file_get_contents avec l'URL. Vous pouvez utiliser l'extension tidy pour analyser le code HTML et extraire le contenu. http://php.net/tidy

1

Vous pouvez télécharger le fichier en utilisant fopen() ou file_get_contents(), comme Raoul Duke dit, mais si vous avez une expérience avec le modèle DOM JavaScript, le DOM extension peut-être un peu plus facile à utiliser que Tidy.

Je sais pertinemment que l'extension DOM est activée par défaut en PHP, mais je ne sais pas si Tidy est (la page de manuel dit seulement qu'elle est "bundelée", donc je suspecte qu'elle ne soit pas activée) .

Questions connexes