Использование множественного поиска в foreach с QueryPath - PullRequest
3 голосов
/ 06 декабря 2011

Я использую QueryPath и PHP.

Это находит .eventdate в порядке, но ничего не возвращает для .dtstart:

$qp = htmlqp($url);
foreach ($qp->find('table#schedule')->find('tr') as $tr){
    echo 'date: ';
    echo $tr->find('.eventdate')->text();
    echo ' time: ';
    echo $tr->find('.dtstart')->text();
    echo '<br>';
}

Если я поменяю местами, .dtstart работает нормально, но .eventdate ничего не возвращает. Таким образом, кажется, что find () в querypath уничтожает элемент и возвращает только необходимое ему значение, что делает невозможным поиск по нескольким элементам итерации по $ tr.

Вот пример HTML для TR, с которым я имею дело:

<tr class="event"><th class="date first" scope="row"><abbr class="eventdate" title="Thursday, February 01, 2011" >02/01</abbr><span class="eventtime" ><abbr class="dtstart" title="2012-02-01T19:00:00" >7:00 PM</abbr><abbr class="dtend" title="2012-02-01T21:00:00" >9:00 PM</abbr></span></th><td class="opponent summary"><ul><li class="first">@ <a class="team" href="/high-schools/ridge-wolves/basketball-winter-11-12/schedule.htm" >Ridge </a> <span class="game-note">*</span></li><li class="location" title="Details: Ridge High School">Details: Ridge High School</li><li class="last"><a class="" href="/local/stats/pregame.aspx?contestid=4255-4c6c-906d&amp;ssid=381d-49f5-9f6d" >Preview Game</a></li></ul></td><td class="result last"><a class="pregame" href="/local/stats/pregame.aspx?contestid=4255-4c6c-906d&amp;ssid=381d-49f5-9f6d">Preview</a></td></tr>

Я пытался скопировать $ tr до первого поиска и заменить его до второго, но это не сработало.

Как я могу искать в каждом $ tr определенные переменные?

К вашему сведению, кроме .eventdate и .dtstart, я также хочу .opponent, href под a для оппонента и a якорный текст.

Ответы [ 3 ]

9 голосов
/ 23 мая 2012

QueryPath поддерживает свое состояние внутри (в отличие от jQuery) по соображениям производительности.Таким образом, branch() - это путь.

В качестве модификации предложенного решения я бы предложил минимизировать количество вызовов find (), выполнив это:

$qp = htmlqp($url);
foreach ($qp->find('table#schedule tr') as $tr){
    echo 'date: ';
    echo $tr->branch('.eventdate')->text();
    echo ' time: ';
    echo $tr->branch('.dtstart')->text();
    echo '<br>';
}

Наконец, всякий раз, когда вы делаете «разрушительное» действие (например, find()), вы всегда можете вернуться на один шаг назад, используя end().Таким образом, вышеприведенное также можно сделать следующим образом:

$qp = htmlqp($url);
foreach ($qp->find('table#schedule tr') as $tr){
    echo 'date: ';
    echo $tr->find('.eventdate')->text();
    echo ' time: ';
    echo $tr->end()->find('.dtstart')->text();
    echo '<br>';
}

Это ОЧЕНЬ ОЧЕНЬ незначительное улучшение производительности, но я предпочитаю метод branch(), если я не работаю с документами размером более 1M.

В QueryPath 3.x, в котором есть целый ряд новых улучшений производительности, я согласен с идеей использования способа jQuery для создания нового объекта для каждой функции.К сожалению, этот метод будет использовать гораздо больше памяти, поэтому я не могу сохранить его.Хотя branch() требуется немного времени, чтобы учиться, у него есть свои преимущества.

8 голосов
/ 06 декабря 2011

Я просто изучаю QueryPath, но я думаю, что вы должны разветвлять объект строки. В противном случае $tr->find('.eventdate') приведет вас к элементу abbr, содержащемуся в строке, и каждый следующий find() будет пытаться найти элементы ниже abbr, в результате чего совпадений не будет. branch() (см. документация ) создает копию объекта QueryPath, оставляя исходный объект (в данном случае $tr) без изменений.

Итак, ваш код будет:

$qp = htmlqp($url);
foreach ($qp->find('table#schedule')->find('tr') as $tr){
    echo 'date: ';
    echo $tr->branch()->find('.eventdate')->text();
    echo ' time: ';
    echo $tr->branch()->find('.dtstart')->text();
    echo '<br>';
}

Я не знаю, является ли это предпочтительным способом достижения того, чего вы хотите, но, похоже, это сработает.

0 голосов
/ 09 апреля 2012

да, вы правы, у меня на самом деле была эта проблема сегодня, в jquery, вы просто запрашиваете, запрашиваете, запрашиваете, не запрашиваете проблем, однако QueryPath, если вы запрашиваете, изменяет внутреннее «состояние» объекта, поэтому, если вы попытаетесьвторой запрос, он применяется к текущему состоянию.

, поэтому, если вы хотите запросить несколько «отдельных» мест в документе, вы должны выполнить ветвление до

$ q = qp («что-то».html);$ a = $ q-> branch () -> find ("tr");$ b = $ q-> branch () -> find ("a");

, кажется, работает в моем коде, поэтому я полагаю, что он будет работать в вашем коде.

...