$domxpath->query - Table 内容
$domxpath->query - Table Contents
大约两天我收到了使用 DOM 文档而不是正则表达式的建议
我还是不知道如何正确使用查询
下面的link里面是session"TERRITÓRIO E AMBIENTE",我想获取下面这4行的内容
https://cidades.ibge.gov.br/brasil/sp/sao-paulo/panorama
$html = file_get_contents( 'https://cidades.ibge.gov.br/brasil/sp/sao-paulo/panorama' );
$document = new DOMDocument();
$document->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
$domxpath = new DOMXPath($document);
$paragraphs = $domxpath->query('
//th[*[
contains(text(), "TERRITÓRIO E AMBIENTE")
]
]
/following-sibling::tr[
position() = 12
]'
);
我输入了 12 <tr>
因为这是源代码中出现的内容,但我不知道我是否正确执行此查询,这对我来说是出现这些错误
Warning: DOMDocument::loadHTML(): Tag app invalid in Entity, line: 25
Warning: DOMDocument::loadHTML(): Misplaced DOCTYPE declaration in Entity, line: 25
Warning: DOMDocument::loadHTML(): htmlParseStartTag: misplaced <html> tag in Entity, line: 25
谢谢
您的代码中存在几个问题。
- 你从那个网站得到的HTML是无效的,所以你需要忽略错误(一般不建议这样做,但在这种情况下我认为可以)。
@$document->loadHTML($html);
- 您要查找的文本是小写的(由于其样式,它显示为大写),因此您需要对其进行规范化或将文本设置为小写
- 你的做法(生第12胎)太脆弱了。我稍微检查了一下代码,很难让它不那么脆弱,但我认为这很接近:
//th[contains(text(), "Território e Ambiente")]/parent::tr/following-sibling::tr[1]/td[3]
获取包含文本Território e Ambiente
的th
元素,然后获取父tr
标签,然后转到下一个tr
兄弟,最后获取第三个 td
元素(值所在的位置)。仍然非常脆弱,但请留意网站的变化,它不太可能改变。
所以现在您需要再重复该 XPath 查询 3 次,更改第 n 个 tr
兄弟(添加两个,因为每个中间都有一个空元素)。它最终看起来像这样:
$document = new DOMDocument();
@$document->loadHTML($html);
$domxpath = new DOMXPath($document);
$paragraphs = $domxpath->query('//th[contains(text(), "Território e Ambiente")]/parent::tr/following-sibling::tr[1]/td[3]');
echo "First: ".preg_replace('/\s+/', ' ', $paragraphs[0]->nodeValue);
echo "<br>";
$paragraphs = $domxpath->query('//th[contains(text(), "Território e Ambiente")]/parent::tr/following-sibling::tr[3]/td[3]');
echo "Second: ".preg_replace('/\s+/', ' ', $paragraphs[0]->nodeValue);
echo "<br>";
$paragraphs = $domxpath->query('//th[contains(text(), "Território e Ambiente")]/parent::tr/following-sibling::tr[5]/td[3]');
echo "Third: ".preg_replace('/\s+/', ' ', $paragraphs[0]->nodeValue);
echo "<br>";
$paragraphs = $domxpath->query('//th[contains(text(), "Território e Ambiente")]/parent::tr/following-sibling::tr[7]/td[3]');
echo "Fourth: ".preg_replace('/\s+/', ' ', $paragraphs[0]->nodeValue);
First: 1.521,110 km²
Second: 92,6 %
Third: 74,8 %
Fourth: 50,3 %
注意使用 preg_replace()
来去除大量空白。
并且使用更多的 XPath 魔法,我们可以让它只处理一个查询:
//th[contains(text(), "Território e Ambiente")]/parent::tr/following-sibling::tr[position() mod 2 = 1]/td[3]
与其他元素的工作方式相同,但不是获取特定的 tr
兄弟元素,而是获取所有其他元素。
$paragraphs = $domxpath->query('//th[contains(text(), "Território e Ambiente")]/parent::tr/following-sibling::tr[position() mod 2 = 1]/td[3]');
foreach ($paragraphs as $i => $p) {
echo ($i + 1)." value: ".preg_replace('/\s+/', ' ', $p->nodeValue);
echo "<br>";
}
大约两天我收到了使用 DOM 文档而不是正则表达式的建议
我还是不知道如何正确使用查询
下面的link里面是session"TERRITÓRIO E AMBIENTE",我想获取下面这4行的内容
https://cidades.ibge.gov.br/brasil/sp/sao-paulo/panorama
$html = file_get_contents( 'https://cidades.ibge.gov.br/brasil/sp/sao-paulo/panorama' );
$document = new DOMDocument();
$document->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
$domxpath = new DOMXPath($document);
$paragraphs = $domxpath->query('
//th[*[
contains(text(), "TERRITÓRIO E AMBIENTE")
]
]
/following-sibling::tr[
position() = 12
]'
);
我输入了 12 <tr>
因为这是源代码中出现的内容,但我不知道我是否正确执行此查询,这对我来说是出现这些错误
Warning: DOMDocument::loadHTML(): Tag app invalid in Entity, line: 25
Warning: DOMDocument::loadHTML(): Misplaced DOCTYPE declaration in Entity, line: 25
Warning: DOMDocument::loadHTML(): htmlParseStartTag: misplaced <html> tag in Entity, line: 25
谢谢
您的代码中存在几个问题。
- 你从那个网站得到的HTML是无效的,所以你需要忽略错误(一般不建议这样做,但在这种情况下我认为可以)。
@$document->loadHTML($html);
- 您要查找的文本是小写的(由于其样式,它显示为大写),因此您需要对其进行规范化或将文本设置为小写
- 你的做法(生第12胎)太脆弱了。我稍微检查了一下代码,很难让它不那么脆弱,但我认为这很接近:
//th[contains(text(), "Território e Ambiente")]/parent::tr/following-sibling::tr[1]/td[3]
获取包含文本Território e Ambiente
的th
元素,然后获取父tr
标签,然后转到下一个tr
兄弟,最后获取第三个 td
元素(值所在的位置)。仍然非常脆弱,但请留意网站的变化,它不太可能改变。
所以现在您需要再重复该 XPath 查询 3 次,更改第 n 个 tr
兄弟(添加两个,因为每个中间都有一个空元素)。它最终看起来像这样:
$document = new DOMDocument();
@$document->loadHTML($html);
$domxpath = new DOMXPath($document);
$paragraphs = $domxpath->query('//th[contains(text(), "Território e Ambiente")]/parent::tr/following-sibling::tr[1]/td[3]');
echo "First: ".preg_replace('/\s+/', ' ', $paragraphs[0]->nodeValue);
echo "<br>";
$paragraphs = $domxpath->query('//th[contains(text(), "Território e Ambiente")]/parent::tr/following-sibling::tr[3]/td[3]');
echo "Second: ".preg_replace('/\s+/', ' ', $paragraphs[0]->nodeValue);
echo "<br>";
$paragraphs = $domxpath->query('//th[contains(text(), "Território e Ambiente")]/parent::tr/following-sibling::tr[5]/td[3]');
echo "Third: ".preg_replace('/\s+/', ' ', $paragraphs[0]->nodeValue);
echo "<br>";
$paragraphs = $domxpath->query('//th[contains(text(), "Território e Ambiente")]/parent::tr/following-sibling::tr[7]/td[3]');
echo "Fourth: ".preg_replace('/\s+/', ' ', $paragraphs[0]->nodeValue);
First: 1.521,110 km²
Second: 92,6 %
Third: 74,8 %
Fourth: 50,3 %
注意使用 preg_replace()
来去除大量空白。
并且使用更多的 XPath 魔法,我们可以让它只处理一个查询:
//th[contains(text(), "Território e Ambiente")]/parent::tr/following-sibling::tr[position() mod 2 = 1]/td[3]
与其他元素的工作方式相同,但不是获取特定的 tr
兄弟元素,而是获取所有其他元素。
$paragraphs = $domxpath->query('//th[contains(text(), "Território e Ambiente")]/parent::tr/following-sibling::tr[position() mod 2 = 1]/td[3]');
foreach ($paragraphs as $i => $p) {
echo ($i + 1)." value: ".preg_replace('/\s+/', ' ', $p->nodeValue);
echo "<br>";
}