我正在为网页的某些特定部分抓取一些网页。我使用php
,curl
和xpath
来获取页面的部分。但是人们建议我应该使用namespaces
XHTML
文档来XPATHs
工作。据我所知namespaces
用于避免各种元素名称之间的冲突,为什么在这种情况下我需要namespaces
?我实际上是使用Tidy将网页转换为XHTML。我是否真的需要命名空间,如果是,在哪种情况下是因为相同的代码without namespaces
适用于从wikipedia
抓取内容。即使修改我的PHP代码以包含namespaces
后,代码也无法用于某些网址。你可以看看这个post。
答案 0 :(得分:3)
首先:命名空间是XML中的基本概念。如果您不熟悉命名空间,请花些时间学习和理解它们。
当且仅当您正在处理的XML文档使用名称空间时,您需要在XPath表达式中使用名称空间前缀。
所有XPath(1.0)名称测试都使用限定名称,即没有名称空间前缀的表达式始终只与无名称空间中的目标匹配。这意味着表达式/element-1/element-2
总是在搜索没有命名空间定义的元素(换句话说:它们属于无命名空间,换句话说:它们具有空命名空间URI)。示例XPath表达式适用于此文档...
<element-1>
<element-2>Works!</element-2>
</element-1>
...但它不适用于此文件...
<ns:element-1 xmlns:ns="http://example.com">
<ns:element-2>Doesn't work</ns:element-2>
</ns:element-1>
...因为在这种情况下<element-1>
和<element-2>
都属于命名空间(URI http://example.com
)。另请注意,如果文档具有默认命名空间,则元素可能属于命名空间,即使它们没有任何命名空间前缀。这份文件......
<element-1 xmlns="http://example.com">
<element-2>Similar to previous, and doesn't work either.</element-2>
</element-1>
...与第二个文档示例相同,并且在其上使用XPath也需要使用名称空间前缀。
从此文档中搜索数据需要使用一些前缀注册名称空间URI,然后在XPath表达式中使用该前缀。像/px:element-1/px:element-2
这样的东西。请注意,您注册的前缀不需要与文档中使用的前缀匹配,但URI必须完全匹配。另一点需要注意的是,即使默认命名空间中的元素没有前缀,您仍然需要使用在XPath表达式中定义的前缀来匹配它们。
因此,XPath查询中对名称空间前缀的需求取决于文档。一些网站将其页面作为有效的XHTML文档提供,因此所有元素都属于XHTML命名空间。其他一些网站提供没有命名空间的HTML或XHTML,这在技术上是无效的XHTML。
命名空间前缀的注册方式取决于您使用的XML框架或库。在php和SimpleXML中,这大致就是这样做的
$your_xml_doc->registerXPathNamespace("ns", "http://example.com");
$result = $your_xml_doc->xpath('/ns:element-1/ns:element-2');
答案 1 :(得分:1)
可以 使用不使用名称空间的XPath表达式。
如果您正在抓取Web内容并且不确定它是XHTML还是未绑定到命名空间的格式良好的HTML,那么您可能会发现为XPath使用更通用的匹配条件会更方便忽略元素的命名空间。
您可以通过任何元素的通用匹配(例如*
)来执行此操作,然后对元素的local-name()
使用谓词过滤器(例如*[local-name()='table']
)。
这样做将匹配具有该名称的任何元素,无论它是否绑定到特定命名空间。
例如:
//*[local-name()='body']/*[local-name()='table'][4]
/*[local-name()='tbody']/*[local-name()='tr'][3]
/*[local-name()='td'][4]