使用Scrapy获取属性名称XPATH
我试图在XML文件(使用scrapy和xpath)中获取某些标记的属性值和键值。使用Scrapy获取属性名称XPATH
的标签是这样的:
<element attr1="value1" attr2="value2 ...>
我不知道钥匙“attR1位”,“attR2位”等等,它们可以在两个元素之间改变。我没有弄清楚如何用xpath获取键和值,还有其他的好做法吗?
短版
>>> for element in selector.xpath('//element'):
... attributes = []
... # loop over all attribute nodes of the element
... for index, attribute in enumerate(element.xpath('@*'), start=1):
... # use XPath's name() string function on each attribute,
... # using their position
... attribute_name = element.xpath('name(@*[%d])' % index).extract_first()
... # Scrapy's extract() on an attribute returns its value
... attributes.append((attribute_name, attribute.extract()))
...
>>> attributes # list of (attribute name, attribute value) tuples
[(u'attr1', u'value1'), (u'attr2', u'value2')]
>>> dict(attributes)
{u'attr2': u'value2', u'attr1': u'value1'}
>>>
龙版
的XPath有name(node-set?)
function得到节点名称(an attribute is a node, an attribute node):
的名˚F (...)如果它省略的参数为,它默认为一个节点集,其中包含一个QName,它代表参数node-set中节点的展开名称, 上下文节点作为其唯一成员。
(来源:http://www.w3.org/TR/xpath/#function-name)
>>> import scrapy
>>> selector = scrapy.Selector(text='''
... <html>
... <element attr1="value1" attr2="value2">some text</element>
... </html>''')
>>> selector.xpath('//element').xpath('name()').extract()
[u'element']
(在此,我//element
选择的结果链式name()
,给函数应用到所有选定元素节点Scrapy选择的一个方便的功能。)
一个想要做同样的属性节点,对不对?但它不工作:
>>> selector.xpath('//element/@*').extract()
[u'value1', u'value2']
>>> selector.xpath('//element/@*').xpath('name()').extract()
[]
>>>
注:我不知道,如果它是lxml/libxml2
的限制,这Scrapy引擎盖下使用,或如果XPath规范禁止它。 (我不明白为什么会这样)
你可以做的是使用name(node-set)
形式,即以非空节点集作为参数。如果仔细阅读的XPath的部分1.0规格我上面粘贴,与其他字符串的功能,name(node-set)
仅考虑在节点集合(按文档顺序)的第一节点:
>>> selector.xpath('//element').xpath('@*').extract()
[u'value1', u'value2']
>>> selector.xpath('//element').xpath('name(@*)').extract()
[u'attr1']
>>>
属性节点也有位置,所以你可以通过它们的位置循环所有属性。在这里,我们有2个(共count(@*)
上下文节点上的结果):
>>> for element in selector.xpath('//element'):
... print element.xpath('count(@*)').extract_first()
...
2.0
>>> for element in selector.xpath('//element'):
... for i in range(1, 2+1):
... print element.xpath('@*[%d]' % i).extract_first()
...
value1
value2
>>>
现在,你能猜到是什么,我们可以这样做:叫name()
每个@*[i]
>>> for element in selector.xpath('//element'):
... for i in range(1, 2+1):
... print element.xpath('name(@*[%d])' % i).extract_first()
...
attr1
attr2
>>>
如果你把所有这些组合起来,并假定@*
将让你在文档顺序属性(在XPath 1.0规范,我认为不说,但它是我所看到的与lxml
发生),你结束了这一点:
>>> attributes = []
>>> for element in selector.xpath('//element'):
... for index, attribute in enumerate(element.xpath('@*'), start=1):
... attribute_name = element.xpath('name(@*[%d])' % index).extract_first()
... attributes.append((attribute_name, attribute.extract()))
...
>>> attributes
[(u'attr1', u'value1'), (u'attr2', u'value2')]
>>> dict(attributes)
{u'attr2': u'value2', u'attr1': u'value1'}
>>>
我想在XML文件(使用scrapy和xpath)中获取某些标记的属性值的键和值。
您需要@*
,这意味着“任何属性”。 XPath表达式//element/@*
将为您提供元素element
的所有属性以及属性及其值。