【发布时间】:2015-03-30 07:42:47
【问题描述】:
我正在编写一个通用的 HTML 浏览器,它可以执行一系列操作,例如访问页面、查找表、查找行、存储数据等。它内部使用 Goutte/Guzzle,因此可以使用 CSS 和 XPath选择器。我遇到了一个有趣的问题,即选择相对于现有结果集的新结果集。
考虑这个演示 HTML:
<h2>Burrowing</h2>
<ul>
<li>
<a href="/jobs/junior-mole">Junior Mole</a>
</li>
<li>
<a href="/jobs/head-of-badger-partnerships">Head of Badger Partnerships</a>
</li>
<li>
<a href="/jobs/trainee-worm">Trainee Worm</a>
</li>
</ul>
<h2>Tree Surgery</h2>
<ul>
<li>
<a href="/jobs/senior-woodpecker">Senior Woodpecker</a>
</li>
<li>
<a href="/jobs/owl-supervisor">Owl Supervisor</a>
</li>
</ul>
<h2>Grass maintenance</h2>
<ul>
<li>
<a href="/jobs/trainee-sheep">Trainee sheep</a>
</li>
<li>
<a href="/jobs/sheep-shearer">Sheep shearer</a>
</li>
</ul>
<h2>Aerial supervision</h2>
<ul>
<li>
<a href="/jobs/head-magpie-ops">Head of Magpie Operations</a>
</li>
</ul>
我运行这个 CSS 查询来获取链接中的角色(这正确地获取了八个项目):
ul li a
对于每一个,我想获取类别,即在每种情况下,<h2> 紧接在 <ul> 之前。现在我可以用一个绝对的 CSS 选择器来做到这一点:
h2
但是,这得到了四个结果,所以我不知道哪个类别 (h2) 与哪个工作 (链接)。我需要得到八个结果:第一个类别的三个批次、第二个类别的两个批次、第三个批次的两个批次和第四个批次的一个批次,因此每个类别映射到每个角色。
我想知道我是否需要一个父选择器,所以我从 CSS 切换到 XPath,并首先尝试了这个,它使每个 h2 都有一个紧随其后的列表项:
//h2[(following-sibling::ul)[1]/li/a]
找到具有指定父结构的 h2,但又返回四个结果 - 不好。
下一次尝试:
//ul/li[../preceding-sibling::h2[1]]
这会获得正确数量的结果(基于获得带有紧接在前面的标题的列表项),但会获得链接文本,而不是类别文本。
我想过做一个循环——我知道我有八个结果,所以我可以这样做(X 是一个从 1 到 8 循环的注入变量)。这可行,但我认为在这里添加手动循环相当不雅 - 我试图让我的规则尽可能通用:
//li[X]/../preceding-sibling::h2[1]
是否有可以返回所需结果的 XPath 操作?为免生疑问,我正在寻找以下内容(或者只是文本元素就可以了):
<h2>Burrowing</h2>
<h2>Burrowing</h2>
<h2>Burrowing</h2>
<h2>Tree Surgery</h2>
<h2>Tree Surgery</h2>
<h2>Grass maintenance</h2>
<h2>Grass maintenance</h2>
<h2>Aerial supervision</h2>
CSS 也可以,但我认为这是不可能的,因为 CSS 没有父运算符(无论如何,Goutte 只是将 CSS 选择器转换为 XPath 选择器)。
由于我使用的是 PHP (5.5),我相信我必须坚持使用 XPath 1.0。
【问题讨论】:
-
跑题了……你的代表怎么了?
-
也许您是其他用户?我以前看到的
halfer有几万……我很困惑…… -
@prodigitalson:不是我,还没有突破 10K 线!快到了……
标签: php xpath css-selectors