抓取同级标签并关联为父子关系

Scrape sibling tags and associate as a parent-child relationship

提问人:Arcade 提问时间:11/5/2022 最后编辑:mickmackusaArcade 更新时间:11/5/2022 访问量:84

问:

我想使用 PHP 从两个不同的标签中提取内容。我想将 h2 标签与紧随其后的 div 标签的内容相关联——就像父子关系一样。

<h1>Title 1</h1>
<div class="items">some data and divs here 1</div>
<h1>Title 2</h1>
<div class="items">some data and divs here 2</div>
<div class="items">some data and divs here 3</div>
<h1>Title 3</h1>
<div class="items">some data and divs here 4</div>
<div class="items">some data and divs here 5</div>
<div class="items">some data and divs here 6</div>

两个 H1 标签之间的项目数不同。

我知道如何使用 simple_html_dom 或 Goutte\Client 抓取所有标签以获得:

<h1>Title 1</h1>
<h1>Title 2</h1>
<h1>Title 3</h1>

<div class="items">some data and divs here 1</div>
<div class="items">some data and divs here 2</div>
<div class="items">some data and divs here 3</div>
<div class="items">some data and divs here 4</div>
<div class="items">some data and divs here 5</div>
<div class="items">some data and divs here 6</div>

但是我无法将标题与数据相关联。我无法弄清楚如何拥有这样的数组:

array (
  0 => 
  array (
    'item' => 'Title 1',
    'data' => 'some data and divs here 1',
  ),
  1 => 
  array (
    'item' => 'Title 2',
    'data' => 'some data and divs here 2',
  ),
  2 => 
  array (
    'item' => 'Title 2',
    'data' => 'some data and divs here 3',
  ),
  3 => 
  array (
    'item' => 'Title 3',
    'data' => 'some data and divs here 4',
  ),
  4 => 
  array (
    'item' => 'Title 3',
    'data' => 'some data and divs here 5',
  ),
  5 => 
  array (
    'item' => 'Title 3',
    'data' => 'some data and divs here 6',
  ),
)

我试图实现类似的东西,但没有找到方法。sibling

php 网页抓取 html 解析 domdocument 同级

评论


答:

0赞 IT goldman 11/5/2022 #1

这里有一个想法,使用一些字符串操作将部分包装在 in a 之间(例如)。然后使用 php 通过标签名称(h1 和 span)获取 html 来阅读它h1spanDOMDocument

这是我的尝试:

$html = '<h1>Title 1</h1>
<div class="items">some data and divs here 1</div>
<h1>Title 2</h1>
<div class="items">some data and divs here 2</div>
<div class="items">some data and divs here 3</div>
<h1>Title 3</h1>
<div class="items">some data and divs here 4</div>
<div class="items">some data and divs here 5</div>
<div class="items">some data and divs here 6</div>';

$html = str_replace('</h1>', '</h1><span>', $html);
$html = str_replace('<h1>', '</span><h1>', $html);
$html = "<span>$html</span>";

$xml = new DOMDocument();
$xml->loadHTML($html);

$items = array();
foreach($xml->getElementsByTagName('span') as $item) {
    $items[] = trim($item->nodeValue);
}
array_shift($items);  // ignore first

$titles = array();
foreach($xml->getElementsByTagName('h1') as $title) {
    $titles[] = trim($title->nodeValue);
}

输出 和 :$items$titles

Array
(
    [0] => some data and divs here 1
    [1] => some data and divs here 2
some data and divs here 3
    [2] => some data and divs here 4
some data and divs here 5
some data and divs here 6
)
Array
(
    [0] => Title 1
    [1] => Title 2
    [2] => Title 3
)

评论

0赞 mickmackusa 11/5/2022
问题要求似乎表明标题和相应的数据需要一起保存在一个结果数组中。
0赞 IT goldman 11/5/2022
没错,它们只是 2 个具有匹配索引的相同长度的数组。
0赞 mickmackusa 11/5/2022
结果数组中应有六行 -- 一行包含标题 1 内容,两行包含标题 2 内容,三行包含标题 3 内容。
0赞 IT goldman 11/5/2022
我没有去那里,因为 a) 我不喜欢这个答案,它不可靠,b) 不确定两者之间的实际内容是什么。h1
0赞 mickmackusa 11/5/2022
如果你不喜欢这个答案,你不需要把它保留在页面上。
1赞 mickmackusa 11/5/2022 #2

根据 XPath 直到下一个标签上的答案,我做了很少的修改来生成所需的结果。

代码:(演示)

$doc = new DOMDocument();
$doc->loadHTML($html);
$xpath = new DOMXpath($doc);
$domNodeList = $xpath->query('/html/body/h1');

$result = [];
foreach($domNodeList as $element) {
    // Save the h1
    $item = $element->nodeValue;

    // Loop the siblings unit the next h1
    while ($element = $element->nextSibling) {
        if ($element->nodeName === "h1") {
            break;
        }
        // if Node is a DOMElement
        if ($element->nodeType === 1) {
            $result[] = ['item' => $item, 'data' => $element->nodeValue];
        }
    }
}
var_export($result);