我正在使用Scrapy抓取一些网页。我想编写一个XPath查询,它将在父<div>
内向任何子<a>
节点附加几个字符的文本,同时正常提取div的self
节点的文本。基本上它就像一个普通的descendant-or-self
或//
查询,只是用|
编写并在后代上调用concat
函数(如果它们存在,则为{{} 1}}标签)。
这些都返回一个值:
<a>
my_div.xpath('div[@class="my_class"]/text()).extract()
my_div.xpath('concat(\'@\', div[@class="my_class"]/a/text())').extract()
然而,尝试以(3)的格式组合上述(1)和(2):
my_div.xpath('div[@class="my_class"]/text() | div[@class="my_class"]/a/text()').extract()
导致以下错误:
my_div.xpath('div[@class="my_class"]/text() |
concat(\'@\', div[@class="my_class"]/a/text())').extract()
如何让XPath识别节点与节点上调用的函数的并集?
答案 0 :(得分:0)
我认为它不起作用,因为concat实际上并没有返回路径,而|
用于选择多个路径
使用|在XPath表达式中,您可以选择多个路径。
根据http://www.w3schools.com/xsl/xpath_syntax.asp
为什么不将它分成两部分呢?通常,您将ItemLoaders与蜘蛛一起使用。因此,您可以根据需要添加任意数量的路径和/或值。
mil = MyItemLoader(response=response)
mil.add_xpath('name', 'xpath1')
mil.add_xpath('name', 'xpath2')
mil.load_item()
# {'name': ['values_of_xpath1','values_of_xpath2']
如果您想保留树顺序,可以尝试:
nodes = my_div.xpath('div[@class="my_class"]')
text = []
for node in nodes:
text.append(node.xpath("text()").extract_first())
text.append(node.xpath("a/text()").extract_first())
text = '@'.join(text)
你可以用列表理解来简化它,但你明白了:提取节点并迭代两个值的节点。
答案 1 :(得分:0)
在XPath 1.0中,location path返回node-set。 concat
函数返回string。 union operator |
计算其操作数的并集,它必须是 node-sets 。
答案 2 :(得分:0)
更新:这就是我所做的:
item['div_text'] = []
div_nodes = definition.xpath('div[@class="my_class"]/a | div[@class="my_class"]/text()')
for n in div_nodes:
if n.xpath('self::a'):
item['div_text'].append("@%s" % n.xpath('text()').extract_first())
else:
item['div_text'].append(n.extract())