Как разобрать HTML-страницу с помощью PHP? - PullRequest
1 голос
/ 21 августа 2010

Разбор HTML / JS-кодов для получения информации с помощью PHP.

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

Посмотрите на эту страницу, это магазин одежды для детей.Это один из их пунктов, и я хочу отметить размер раздела.Здесь нам нужно получить все размеры для этого элемента и проверить, доступны ли размеры.Прямо сейчас все размеры для этого элемента:

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

Как вы можете сказать, доступны ли размеры или нет?

Теперь сначала посмотрите на эту страницу и проверьте размеры снова:

www.asos.com / Ralph-Lauren / Ralph-Lauren-Длинный рукав-Большой-конь-полоса-Регби-топ / Prod / pgeproduct.aspx? Iid = 1111751

Этот товар имеет следующие размеры:

12 months
18 months - Not Available
24 months

Как видно, 18-месячный размер недоступен, он обозначен текстом "Недоступно" рядом с размером.

Что мынужно сделать, это перейти на страницу элемента, получить размеры и проверить наличие каждого размера.Как я могу сделать это в PHP?

РЕДАКТИРОВАТЬ:

Добавлен рабочий код и новая проблема для решения.

Рабочий код, но он требует дополнительной работы:

<?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();
}

?>

Приведенный выше код работает, но возникает проблема, когда продукт требует, чтобы вы сначала выбрали цвет перед отображением размеров.

Как этот:

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

Есть идеи, как это сделать?

Ответы [ 3 ]

3 голосов
/ 21 августа 2010

РЕШЕНИЕ:

    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);

Ссылка: http://debconf11.com/stackoverflow.php

Теперь вы по своему усмотрению:)

EDIT2:

Хорошо, мыблизки к решению ...

<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>

Он не загружается через ajax, вместо этого массив находится в переменной javascript.Вы можете разобрать это с помощью PHP, вы можете ясно видеть, что 18 месяцев - это Ложь, что означает, что она недоступна.

РЕДАКТИРОВАТЬ:

Эти размеры загружаются с помощью JavaScript, поэтому вы не можете анализировать их, так как их там нет.Я могу извлечь только это ...

<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>

Вы можете прослушать JS, чтобы проверить, можете ли вы загружать размеры на основе идентификатора продукта.


Сначала вам нужно: http://simplehtmldom.sourceforge.net/ Забудьте file_get_contents (), что он примерно на 5 медленнее, чем cURL.

Затем вы анализируете этот фрагмент кода (html с идентификатором 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>

Затем можно использовать preg_match ()explode (), str_replace () и другие, чтобы отфильтровать нужные значения.Я могу написать это, но у меня сейчас нет времени :) 1031

1 голос
/ 21 августа 2010

Вы можете скачать файл, используя fopen() или file_get_contents(), как сказал Рауль Дьюк, но если у вас есть опыт работы с моделью DOM JavaScript, то DOMрасширение может быть немного проще в использовании, чем Tidy.

Я точно знаю, что расширение DOM включено по умолчанию в PHP, но я немного не уверен, что Tidy есть (только страница справочника)говорит, что он «запутан», поэтому я подозреваю, что он может быть не включен).

1 голос
/ 21 августа 2010

Самый простой способ получить содержимое URL-адреса - использовать fopen оболочки и просто использовать file_get_contents с URL-адресом.Вы можете использовать расширение Tidy для разбора HTML и извлечения контента.http://php.net/tidy

...