使用xpath对html进行子过滤

时间:2014-05-25 14:14:19

标签: symfony xpath web-crawler

我怀疑实现这一目标的最佳途径。我正在使用Symfony Crawler,我有这个过滤器:

$myData = $crawler->filterXPath('//div[@class="container"]');

然后我就这样循环:

      foreach ($myData as $domElementData) {

但是使用divFirst我得到一个带有链接,div,...的块我需要过滤并为每个块放入一个数组。我的第一种方法是循环遍历每个块(divFirst)然后进行子过滤,但是我不确定是否应该为此创建第二个子爬行器?

另一种选择是做类似的事情:

$subData1 = $crawler->filterXPath('//*[contains(@id, "date")]');
$subData2 = $crawler->filterXPath('//*[contains(@id, "price")]');
...

然后循环第一个并使用它的索引在第一个数组中包含fest of fields的所有信息?

foreach (subData1 as $index=>$subData) {
  $theFinalData [$index]['subdata1'] = subData1;
  $theFinalData [$index]['subdata2'] = subData2;
  ...

但这最后的选择似乎很奇怪甚至丑陋。有什么意见吗?

我试图阅读的HTML看起来像这样:

<div class="container1234Y53">
  <div id="date12345">12/02/2014</div>
  <div id="price">80£</div>
  <div id="numberofpeople">4</div>
</div>
  <div class="container1234X123">
  <div id="date3451">2/06/2014</div>
  <div id="price">30£</div>
  <div id="numberofpeople">1</div>
</div>
....

结果应该是这样的数组:

container[0]['date'] = 12/02/2014
container[0]['price'] = 80
container[0]['numberofpeople'] = 4
container[1]['date'] = 2/06/2014
container[1]['price'] = 30
container[1]['numberofpeople'] = 1
....

提前多多感谢。

1 个答案:

答案 0 :(得分:1)

经过一番研究,我回答自己希望能帮助别人。

您必须创建一个新的Crawler,如下所示:http://www.ymc.ch/en/webscraping-in-php-with-guzzle-http-and-symfony-domcrawler

基本上,第一个将搜索第一组:

// crate crawler instance from body HTML code
$crawler = new Crawler($response->getBody(true));

// apply css selector filter
$myData = $crawler->filterXPath('//div[@class="container"]');
$result = array();

然后你可以迭代结果,创建一个新的Crawler并使用这个新的抓取工具提取这些新搜索的结果:

// iterate over filter results
foreach ($myData as $i => $content) {

    // create crawler instance for result
    $cralwer = new Crawler($content);
    // extract the values needed
    $result[$i] = array(
        'topic' => $crawler->filterXPath('//*[contains(@id, "date")]')->text();
...

我不确定(我仍然是)这是否是性能方面的最佳解决方案,因为爬虫是多次创建的,但在编码样式方面似乎比第一个解决方案更好。