Simple_DOM вопрос о поиске классов - PullRequest
0 голосов
/ 22 мая 2011

Я пытаюсь выполнить простое извлечение, но получаю непредсказуемые результаты.

У меня есть этот HTML-код

<div class="thread" style="margin-bottom:25px;"> 

<div class="message"> 

<span class="profile">Suzy Creamcheese</span> 

<span class="time">December 22, 2010 at 11:10 pm</span> 

<div class="msgbody"> 

<div class="subject">New digs</div> 

Hello thank you for trying our soap. <BR>  Jim.

</div> 
</div> 


<div class="message reply"> 

<span class="profile">Lars Jörgenmeier</span> 

<span class="time">December 22, 2010 at 11:45 pm</span> 

<div class="msgbody"> 

I never sold you any soap.

</div> 

</div> 

</div> 

И я пытаюсь извлечь внешний текст из"msgbody", но только когда "профиль" равен чему-то.Вот так.

$contents  = $html->find('.msgbody');
$elements = $html->find('.profile'); 

           $length = sizeof($contents);

           while($x != sizeof($elements)) {

            $var = $elements[$x]->outertext;

                        //If profile = the right name
            if ($var = $name) {

                                    $text = $contents[$x]->outertext;
                echo $text;

            }



            $x++;
         }    

Я получаю текст из неправильных профилей, а не из тех, с которыми мне нужны ассоциации.Есть ли способ просто получить нужную информацию одной строкой кода?

Как если бы span-profile = "правильное имя", то потянуть его div-msgbody

Ответы [ 2 ]

3 голосов
/ 22 мая 2011

Хорошо, я собираюсь пойти с DOMXpath на этом.Я не уверен, что подразумевается под «внешним текстом», но я пойду с этим требованием:

Как если бы span-profile = «правильное имя», тогда потяните его div-msgbody

Прежде всего, вот миниатюрный тестовый пример HTML, который я использовал:

<html>
<body>
<div class="thread" style="margin-bottom:25px;"> 

<div class="message"> 

<span class="profile">Suzy Creamcheese</span> 

<span class="time">December 22, 2010 at 11:10 pm</span> 

<div class="msgbody"> 

<div class="subject">New digs</div> 

Hello thank you for trying our soap. <BR>  Jim.

</div> 
</div> 


<div class="message reply"> 

<span class="profile">Lars Jörgenmeier</span> 

<span class="time">December 22, 2010 at 11:45 pm</span> 

<div class="msgbody"> 

I never sold you any soap.

</div> 

</div> 

</div>
</body>
</html>

Итак, мы сделаем запрос XPath для этого.Давайте покажем все это, а затем разобьем его:

$messages = $xpath->query("//span[@class='profile' and contains(.,'$profile_name')]/../div[@class='msgbody']");

Разбивка:

// span

Дайте мне промежутки

// span [@ class = 'profile']

Дайте мне промежутки, где класс является профилем

// span [@ class = 'profile' и содержит (., '$ profile_name')]

Дайте мне промежутки, где класс является профилем, а внутренняя часть промежутка содержит $profile_name, то есть имя, которое вы после

// span [@ class ='profile 'и содержит (.,' $ profile_name ')] /../

Дайте мне промежутки, где класс является профилем, а внутренняя часть промежутка содержит $profile_name, то есть имя, которое вы ищетеТеперь поднимитесь на уровень, который приведет нас к <div class="message">

// span [@ class = 'profile' 'и содержит (.,' $ profile_name ')] /../ div [@ class ='msgbody ']

Дайте мне промежутки, где класс является профилем, а внутренняя часть промежутка содержит $profile_name, то есть имя, за которым вы теперь идете, поднимитесь на уровень, что приведет нас к <div class="message"> инаконец, дайте мне все div в <div class="message">, где класс msgbody

Теперь вот пример кода PHP:

$doc = new DOMDocument();
$doc->loadHTMLFile("test.html");

$xpath = new DOMXpath($doc);
$profile_name = 'Lars Jörgenmeier';
$messages = $xpath->query("//span[@class='profile' and contains(.,'$profile_name')]/../div[@class='msgbody']");
foreach ($messages as $message) {
  echo trim("{$message->nodeValue}") . "\n";
}

XPath очень мощный, как этот.Я рекомендую просмотреть базовый учебник , затем вы можете проверить стандарт XPath , если хотите увидеть более расширенное использование.

0 голосов
/ 02 июля 2011

Это рабочий пример простого HTML DOM.

Я изменил ваш пример html, чтобы для Suzy Creamcheese было более одного профиля: (file: test_class_class.htm)

 <div class="message"> 
   <span class="profile">Suzy Creamcheese</span> 
   <span class="time">December 22, 2010 at 11:10 pm</span> 
   <div class="msgbody"> 
     <div class="subject">New digs</div> 
       Hello thank you for trying our soap. <BR>  Jim.
     </div> 
   </div> 

   <div class="message reply"> 
     <span class="profile">Lars Jörgenmeier</span> 
     <span class="time">December 22, 2010 at 11:45 pm</span> 
     <div class="msgbody"> 
       I never sold you any soap.
     </div> 
   </div> 
 </div>

 <div class="message"> 
   <span class="profile">Suzy Yogurt</span> 
   <span class="time">December 22, 2010 at 11:10 pm</span> 
   <div class="msgbody"> 
     <div class="subject">No Creamcheese</div> 
       This is not Suzy Creamcheese <BR>  Jim.
     </div> 
   </div> 

   <div class="message reply"> 
     <span class="profile">Suzy Creamcheese</span> 
     <span class="time">December 22, 2010 at 11:45 pm</span> 
     <div class="msgbody"> 
       A reply from Suzy Creamcheese.
     </div> 
   </div> 
 </div>

</div>

Вот мой тест с использованием Simple HTML DOM: включают в себя ( 'simple_html_dom.php');

function getMessage_for_profile($iUrl,$iProfile)
{
    // create HTML DOM
    $html = file_get_html($iUrl);

    // get text elements
    $aoProfile = $html->find('span[class=profile]'); 
    echo "Found ".count($aoProfile)." profiles.<br />";

    foreach ($aoProfile as $key=>$oProfile)
    {
      if ($oProfile->plaintext == $iProfile)
      {
        echo "<b>Profile ".$key.": ".$oProfile->plaintext."</b><br />";
// Using $e->next_sibling ()
        $oCurrent = $oProfile;
        while ($oNext = $oCurrent->next_sibling())
        {
           if ( $oNext->class == "msgbody" )
           {
             echo "<hr />";
             echo $oNext->outertext;
             echo "<hr />";
           }
           $oCurrent = $oNext;
        }
      }         
    }

    // clean up memory
    $html->clear();
    unset($html);

    return;
}
// --------------------------------------------
// test it!
// user_agent header...
ini_set('user_agent', 'My-Application/2.5');

getMessage_for_profile('test_class_class.htm','Suzy Creamcheese');
echo "<br /><br /><br />";
getMessage_for_profile('test_class_class.htm','Suzy Yogurt');

Мой вывод был:

Found 4 profiles.
Profile 0: Suzy Creamcheese
--------------------------------
New digs
Hello thank you for trying our soap.
Jim.
---------------------------------
Profile 3: Suzy Creamcheese
---------------------------------
A reply from Suzy Creamcheese.
---------------------------------



Found 4 profiles.
Profile 2: Suzy Yogurt
---------------------------------
No Creamcheese
This is not Suzy Creamcheese
Jim.
---------------------------------

Видите, это можно сделать с помощью простого HTML DOM, и, поскольку я уже знаю, как работает DOM ... или достаточно, чтобы попасть в неприятности ... Мне не нужно было изучать какой-либо известный синтаксис!

...