3

我正在使用 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() 似乎破坏了元素并且只返回它需要的值,使得 $tr 上的迭代无法搜索多个项目。

这是我正在处理的 TR 的示例 HTML:

<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 之外,我还想要a对手下的 .opponent、href 和a锚文本。

4

3 回答 3

9

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>';
}

最后,任何时候你做一个“破坏性”的动作(比如 a 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()需要一点时间来学习,但它确实有它的优势。

于 2012-05-23T01:18:47.890 回答
8

我自己只是在学习 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>';
}

我不知道这是否是实现您想要的首选方式,但它似乎有效。

于 2011-12-06T19:24:41.030 回答
0

是的,你是对的,我今天实际上遇到了这个问题,在 jquery 中,你只是查询,查询,查询,查询没有问题,但是如果你查询 QueryPath,它会改变对象的内部“状态”,所以如果你尝试第二次查询,它适用于当前状态。

因此,如果要查询文档中的多个“单独”位置,则必须先分支

$q = qp("something.html);
$a = $q->branch()->find("tr");
$b = $q->branch()->find("a");

这似乎适用于我的代码,所以我想它适用于你的代码。

于 2012-04-09T13:44:30.823 回答