Linux的
>>> from lxml import etree
>>> html='''<td><a href=''>a1</a></td>
... <td><a href=''>a2</a></td>
... '''
>>> p=etree.HTML(html)
>>> a=p.xpath("//a[1]")
>>> for i in a:
... print i.text
...
a1
a2
窗口。
>>> html='''<td><a href=''>a1</a></td>
... <td><a href=''>a2</a></td>
... '''
>>> from lxml import etree
>>> p=etree.HTML(html)
>>> a=p.xpath("//a[1]")
>>> for i in a:
... print i.text
...
a1
>>> b=p.xpath("//a[2]")
>>> for i in b:
... print i.text
...
a2
在Windows中,我可以轻松使用a[1]
和a[2]
来获取这两个值。
但在Linux中,xpath //a[1]
将这两个链接文本放在一起。
这使得程序在这些操作系统中不那么兼容。我必须修改不同操作系统上的代码。 它是一个lxml模块错误吗?对此有何解决方案?
答案 0 :(得分:6)
我可以在您报告的Linux上确认相同的结果。它返回两个元素的列表,而不是1个单元素。
//a[1]
要求要求任何a
元素首先在其上下文中。
由于a
内嵌有td
元素,因此td
是计算位置的上下文,并且会出现两种情况。
将xpath更改为"(//a)[1]"
可以解决问题。
引自MSDN on Operators and Special Characters
过滤模式运算符([])的优先级高于路径运算符(/和//)。例如,表达式// comment()[3]选择索引等于3的所有注释,相对于文档中任何位置的注释父项。这与表达式(// comment())[3]不同,后者从相对于父项的所有注释的集合中选择第三个注释。第一个表达式可以返回多个注释,而后者只能返回一个注释。
xpath //a[1]
只返回提供文档的一个元素是完全错误的,应该报告给lxml作者。
lxml在不同平台和操作系统上的状态:
为了使您的解决方案具有可移植性,您需要lxml==2.3.0
,因为此版本在Windows上以及在Linux上正常运行(可能有另一个版本在两个平台上运行良好,我没有测试更多)。
假设您已安装nose
$ pip install nose
您可以使用以下test_xpath.py
:
from lxml import etree
import nose
print "=================================="
print "lxml version: ", etree.__version__
print "=================================="
def test_html():
html_str = """
<td><a href=''>a1</a></td>
<td><a href=''>a2</a></td>
"""
doc = etree.HTML(html_str.strip())
elms = doc.xpath("//a[1]")
assert len(elms) == 2, """xpath `//a[1]` shall return 2 elements"""
assert all(elm.tag == "a" for elm in elms), "all returned elements shall be `a`"
assert elms[0].text == "a1"
assert elms[1].text == "a2"
def test_xml():
xml_str = """
<root>
<td><a href=''>a1</a></td>
<td><a href=''>a2</a></td>
</root>
"""
doc = etree.fromstring(xml_str.strip())
elms = doc.xpath("//a[1]")
assert len(elms) == 2, """xpath `//a[1]` shall return 2 elements"""
assert all(elm.tag == "a" for elm in elms), "all returned elements shall be `a`"
assert elms[0].text == "a1"
assert elms[1].text == "a2"
nose.main()
快速执行测试:
$ python test_xpath.py -v
==================================
lxml version: 2.3.0
==================================
test_xpath.test_html ... ok
test_xpath.test_xml ... ok
----------------------------------------------------------------------
Ran 2 tests in 0.002s
OK