我正在尝试选择具有以下结构的表字段:
<td class='postac'>proszek do sporz. roztworu do wlewu <I>i.v.</I>
1,5 g
1 fiol. typu Monovial
</td>
使用xpath表达式sel.xpath("//table[@class='table-postaci']/tbody/tr/td[2]/text()").extract()
后,我得到两个值而不是一个:
u'proszek do sporz. roztworu do wlewu ',
u'\r\n 1,5 g\r\n 1 fiol. typu Monovial\r\n '
将这个“td”字段作为单个值,是否有一些干净的xpath方法?我知道我可以使用//table[@class='table-postaci']/tbody/tr/td[2]
获取字段,然后在scrapy管道中删除标记。但是,我正在寻找一些更简单的解决方案。谢谢
答案 0 :(得分:2)
出于这个原因,你应该避免使用/ text()。通常你不需要单独的文本节点,你需要元素的字符串值,你可以使用string()函数获得。目前尚不清楚您从哪个编程语言调用XPath,或者它是XPath 1.0还是2.0 - 会影响细节,例如:是否在XPath表达式或宿主语言中获取元素的字符串值。
答案 1 :(得分:2)
您可以遍历每个表格行tr
,并为每一行加入第二个td
单元格的所有文本节点后代:
In [13]: from scrapy.selector import Selector
In [14]: selector = Selector(text="""<table class='table-postaci'>
....: <thead><th>Nazwa preparatu</th><th>Postać i dawka</th><th>Producent</th><th>Cena 100%</th>
....: <th>Odpłatność po refundacji</th>
....: </thead>
....: <tbody>
....:
....: <tr>
....: <td class='postac'>Zinacef </td>
....: <td class='postac'>proszek do sporz. roztworu do wlewu <I>i.v.</I>
....: 1,5 g
....: 1 fiol. typu Monovial
....: </td>
....: <td>GlaxoSmithKline – Wielka Brytania</td>
....: <td class='cena'> b/d </td>
....: <td>
....: </td>
....: </tr>
....: <tr>
....: <td class='postac'>Zinacef </td>
....: <td class='postac'>proszek do sporz. roztworu do wlewu <I>i.v.</I>
....: 750 mg
....: 1 fiol. typu Monovial
....: </td>
....: <td>GlaxoSmithKline – Wielka Brytania</td>
....: <td class='cena'> b/d </td>
....: <td>
....: </td>
....: </tr>
....: </tbody>
....: </table""")
In [15]: selector.xpath('//table/tr')
Out[15]: []
In [16]: selector.xpath('//table//tr')
Out[16]:
[<Selector xpath='//table//tr' data=u'<tr><td class="postac">Zinacef </td>\n\t\t<'>,
<Selector xpath='//table//tr' data=u'<tr><td class="postac">Zinacef </td>\n\t\t<'>]
In [17]: for row in selector.xpath('//table//tr'):
....: print row.xpath('td[2]//text()').extract()
....:
[u'proszek do sporz. roztworu do wlewu ', u'i.v.', u'\n 1,5 g\n 1 fiol. typu Monovial\n ']
[u'proszek do sporz. roztworu do wlewu ', u'i.v.', u'\n 750 mg\n 1 fiol. typu Monovial\n ']
In [18]: [u''.join(row.xpath('td[2]//text()').extract()) for row in selector.xpath('//table//tr')]
Out[18]:
[u'proszek do sporz. roztworu do wlewu i.v.\n 1,5 g\n 1 fiol. typu Monovial\n ',
u'proszek do sporz. roztworu do wlewu i.v.\n 750 mg\n 1 fiol. typu Monovial\n ']
In [19]:
答案 2 :(得分:1)
问题中的td
节点有三个子节点 - 首先是一个包含内容的文本节点:
proszek do sporz. roztworu do wlewu
第二个I
元素节点,它有自己的子文本节点,最后一个文本节点包含内容:
\n 1,5 g\n 1 fiol. typu Monovial\n
您的查询(其末尾看起来像td[2]/text()
)仅选择td
元素的直接文本节点子节点,因此它不会选择I
元素节点或其文本节点子。结果是您看到的两个文本节点。
您可以使用td
选择{{1>}元素的所有文本节点decedents(请注意双斜杠td[2]//text()
)。这将在结果中返回三个文本节点 - 两个如上所述,第三个在它们之间包含//
。然后你可以在XPath之外加入他们(我不熟悉scrapy,所以在这种情况下我不能告诉你如何)。
据我所知,你无法直接使用XPath 1.0加入这三个节点,但XPath 2.0可能会加入。