首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Scrapy获取属性名称

使用Scrapy获取属性名称
EN

Stack Overflow用户
提问于 2015-09-25 20:57:01
回答 2查看 5.2K关注 0票数 4

我试图同时获取XML文件中某些标记的键值和属性值(使用scrapy和xpath)。

标签是这样的:

代码语言:javascript
运行
复制
<element attr1="value1" attr2="value2 ...>

我不知道"attr1“、"attr2”等键,它们可以在两个元素之间进行更改。我不知道如何使用xpath同时获得键和值,还有其他好的做法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-09-26 10:30:25

短版

代码语言:javascript
运行
复制
>>> 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函数返回一个字符串,该字符串表示参数节点集中节点的扩展名称(按文档顺序排列)。(.)(.)如果该参数省略了,则默认为以上下文节点为唯一成员的节点集。

(资料来源:http://www.w3.org/TR/xpath/#function-name)

代码语言:javascript
运行
复制
>>> import scrapy
>>> selector = scrapy.Selector(text='''
...     <html>
...     <element attr1="value1" attr2="value2">some text</element>
...     </html>''')
>>> selector.xpath('//element').xpath('name()').extract()
[u'element']

(在这里,我将name()链接到//element选择的结果,以便将该函数应用于所有选定的元素节点。抓取选择器的一个方便的特性)

我们希望对属性节点也这样做,对吗?但它不起作用:

代码语言:javascript
运行
复制
>>> selector.xpath('//element/@*').extract()
[u'value1', u'value2']
>>> selector.xpath('//element/@*').xpath('name()').extract()
[]
>>> 

注意:我不知道这是否是Scrapy在引擎盖下使用的lxml/libxml2的限制,或者XPath规范是否不允许它。(我不明白为什么会这样。)

不过,您可以使用name(node-set)表单,即以非空节点集作为参数。如果您仔细阅读了上面粘贴的XPath 1.0规范的部分,就像其他字符串函数一样,name(node-set)只考虑节点集中的第一个节点(按文档顺序排列):

代码语言:javascript
运行
复制
>>> selector.xpath('//element').xpath('@*').extract()
[u'value1', u'value2']
>>> selector.xpath('//element').xpath('name(@*)').extract()
[u'attr1']
>>> 

属性节点也有位置,因此可以根据属性的位置对所有属性进行循环。这里有2(上下文节点上的count(@*)结果):

代码语言:javascript
运行
复制
>>> 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]

代码语言:javascript
运行
复制
>>> 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中看到的),那么您将得到以下结果:

代码语言:javascript
运行
复制
>>> 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'}
>>> 
票数 9
EN

Stack Overflow用户

发布于 2015-09-25 21:13:50

我试图同时获取XML文件中某些标记的键值和属性值(使用scrapy和xpath)。

您需要@*,意思是“任意属性”。XPath表达式//element/@*将为您提供元素element的所有属性,以及属性的值。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32790549

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档