使用 DOMDocument 和 DOMXPath 根据附近的 header 标签解析 HTML Table
Parsing HTML Table based on nearby header tag using DOMDocument and DOMXPath
我有一个简单的 PHP 应用程序,它解析 html 内容并从 td 中提取与特定查询匹配的数据。
HTML代码:
<html>
<h3>HELLO WORLD</h3>
<table>
<tr><td>A</td><td>A2</td></tr>
<tr><td>B</td><td>B2</td></tr>
...
...
</table>
<h3>HELLO AMERICA</h3>
<table>
<tr><td>A</td><td>A3</td></tr>
<tr><td>C</td><td>C2</td></tr>
...
...
</table>
<h3>HELLO TEXAS</h3>
<table>
<tr><td>D</td><td>D2</td></tr>
<tr><td>E</td><td>E2</td></tr>
...
...
</table>
<html>
PHP 解析 table
的代码
$content = file_get_contents($html_string);
$dom = new DOMDocument();
@$dom->loadHTML($content);
$xpath = new DOMXPath($dom);
$query = "//tr/td[position()=1 and normalize-space(text()) = '".$q."']";
$entries = $xpath->query($query);
$entryCount = $entries->length;
if ($entryCount==1){
$entry = $entries->item(0);
$tr = $entry->parentNode;
foreach ($tr->getElementsByTagName("td") as $td) {
$fieldnames[] = $td->textContent;
}
//Return data set
$data[] = $fieldnames;
return $data;
}
else {
$data = array();
for ($i=0;$i<$entryCount;$i++){
$fieldnames = [];
$entry = $entries->item($i);
$tr = $entry->parentNode;
foreach ($tr->getElementsByTagName("td") as $td) {
$fieldnames[] = $td->textContent;
}
$data[] = $fieldnames;
}
return $data;
}
基本上这将经历所有 3 tables。比方说,我发送一个查询($q = A),它将 return:
$data[0][0] => A, $data[0][1] => A2
$data[1][0] => A, $data[1][1] => A3
但是,我只想要第一个 table 的数据(A 和 A2)。 table 是 'naked'。没有身份证,没有 class 或任何身份证明。唯一能识别它们的是 h3 标签。比方说,我提供了一个指定 h3 ($q2 = HELLO WORLD) 的查询,是否可以仅从第一个 table?
中提取数据
您想使用前同级轴和 [1]
位置谓词(或任何正式名称),并查看 h3
元素的文本内容以找到 h3
元素就是你想要的 table
之前的元素;所以,我想,这:
//table[preceding-sibling::h3[1][. = "HELLO WORLD"]]
或者,要获取示例中的代码正在寻找的特定内容,
//table[preceding-sibling::h3[1][. = "HELLO WORLD"]]/tr/td[position()=1 and normalize-space(text()) = '".$q."']
如果您以后碰巧想要获取任何其他表格,只需换掉该表达式中的文本即可;例如,以下将仅获取示例中的最后一个。
//table[preceding-sibling::h3[1][. = "HELLO TEXAS"]]
我有一个简单的 PHP 应用程序,它解析 html 内容并从 td 中提取与特定查询匹配的数据。
HTML代码:
<html>
<h3>HELLO WORLD</h3>
<table>
<tr><td>A</td><td>A2</td></tr>
<tr><td>B</td><td>B2</td></tr>
...
...
</table>
<h3>HELLO AMERICA</h3>
<table>
<tr><td>A</td><td>A3</td></tr>
<tr><td>C</td><td>C2</td></tr>
...
...
</table>
<h3>HELLO TEXAS</h3>
<table>
<tr><td>D</td><td>D2</td></tr>
<tr><td>E</td><td>E2</td></tr>
...
...
</table>
<html>
PHP 解析 table
的代码$content = file_get_contents($html_string);
$dom = new DOMDocument();
@$dom->loadHTML($content);
$xpath = new DOMXPath($dom);
$query = "//tr/td[position()=1 and normalize-space(text()) = '".$q."']";
$entries = $xpath->query($query);
$entryCount = $entries->length;
if ($entryCount==1){
$entry = $entries->item(0);
$tr = $entry->parentNode;
foreach ($tr->getElementsByTagName("td") as $td) {
$fieldnames[] = $td->textContent;
}
//Return data set
$data[] = $fieldnames;
return $data;
}
else {
$data = array();
for ($i=0;$i<$entryCount;$i++){
$fieldnames = [];
$entry = $entries->item($i);
$tr = $entry->parentNode;
foreach ($tr->getElementsByTagName("td") as $td) {
$fieldnames[] = $td->textContent;
}
$data[] = $fieldnames;
}
return $data;
}
基本上这将经历所有 3 tables。比方说,我发送一个查询($q = A),它将 return:
$data[0][0] => A, $data[0][1] => A2
$data[1][0] => A, $data[1][1] => A3
但是,我只想要第一个 table 的数据(A 和 A2)。 table 是 'naked'。没有身份证,没有 class 或任何身份证明。唯一能识别它们的是 h3 标签。比方说,我提供了一个指定 h3 ($q2 = HELLO WORLD) 的查询,是否可以仅从第一个 table?
中提取数据您想使用前同级轴和 [1]
位置谓词(或任何正式名称),并查看 h3
元素的文本内容以找到 h3
元素就是你想要的 table
之前的元素;所以,我想,这:
//table[preceding-sibling::h3[1][. = "HELLO WORLD"]]
或者,要获取示例中的代码正在寻找的特定内容,
//table[preceding-sibling::h3[1][. = "HELLO WORLD"]]/tr/td[position()=1 and normalize-space(text()) = '".$q."']
如果您以后碰巧想要获取任何其他表格,只需换掉该表达式中的文本即可;例如,以下将仅获取示例中的最后一个。
//table[preceding-sibling::h3[1][. = "HELLO TEXAS"]]