1

我有一个外部 HTML 源,我想抓取它并转换为本地 XML 文件或添加到 MySQL DB。

外部源大多是规范化的和(有点)语义的,所以我需要做的就是使用XPATH来获取所有td内容或所有li内容等。问题是这些项目有时会使用<strong>or <b>or<i>标记来设置我需要的元素的样式。

这在技术上是语义化的,因为重点是要强调特定文本,并且开发人员可能希望使用不是浏览器默认的 CSS。

问题是我试图抓取的实际内容被认为是这个内联元素的子元素,因此 PHP 扩展喜欢simplexmlorDOMDocument并将DOMNode它们视为这样。例如:

<table>
<tr><td>Thing 1</td><td>Thing 2</td></tr>
<tr><td>Thing 3</td><td>Thing 4</td></tr>
<tr><td><strong>Thing 5</strong></td><td><strong>Thing 6</strong></td></tr>
</table>

将导致:

 [table] =>
    [tr] =>
        [td] => Thing 1
        [td] => Thing 2
    [tr] =>
        [td] => Thing 3
        [td] => Thing 4
    [tr] =>
        [td] => 
            [strong] => Thing 5
        [td] => 
            [strong] => Thing 6

显然上面的内容并不是simplexml返回的内容,但上面反映了普遍的问题。

那么有没有一种方法,使用已经内置在 DOMDocument 中的参数或使用更复杂的 XPath 查询来获取td元素的内容,其中任何子项(如果有的话)被剥离其后代状态并将所有内容视为文本查询的元素?

现在,我唯一的解决方案是:

a) 有一个foreach检查每个结果的循环,例如:

$result_text = ($result -> strong) ? $result - strong : $result;

b)<strong>在将 HTML 字符串导入任何预构建类(如 simplexml 或 DOMDocument)之前,使用正则表达式从 HTML 字符串中去除任何标签。

4

3 回答 3

1

如果只是为了娱乐,请在使用正则表达式解析 html 之前阅读第一个答案XPath 就是答案,获取 td 的文本而不是继续解析它。因此,您只需搜索类似的东西//td并完全获取结果(而不是继续构建树,这样您的叶子就可以说强或其他。

于 2010-01-17T08:19:42.530 回答
1

您不能只使用strip_tags()删除额外的标记吗?

$table = simplexml_load_string(
    '<table>
        <tr><td>Thing 1</td><td>Thing 2</td></tr>
        <tr><td>Thing 3</td><td>Thing 4</td></tr>
        <tr><td><strong>Thing 5</strong></td><td><strong>Thing 6</strong></td></tr>
    </table>'
);

foreach ($table->xpath('//td') as $td)
{
    $content = strip_tags($td->asXML());
    echo $content, "\n";
}
于 2010-01-17T08:20:15.497 回答
0

如果您使用的是 DOMDocument,一旦您选择了一个 DOMNode,该属性textContent应该只包含它的文本部分以及它的所有子元素......正是您所要求的。

$table = '<table>
        <tr><td>Thing 1</td><td>Thing 2</td></tr>
        <tr><td>Thing 3</td><td>Thing 4</td></tr>
        <tr><td><strong>Thing 5</strong></td><td><strong>Thing 6</strong></td></tr>
    </table>';

$dom = new DOMDocument;
$dom->loadHTML($table);
$xpath = new DOMXPath($dom);

$els = $xpath->query('//td');
echo $els->item(4)->textContent; //Thing 5

或者,根据节点的类型,您也可以进行检查nodeValue。我不记得确切的区别,但textContent是你想要的。

于 2010-01-17T09:22:02.500 回答