请注意:基于lxml的Scrapy选择器与lxml的行为与布尔XPath表达式的结果或那些返回数字的行为不同。
让我们用这个样本HTML文件来说明:
>>> html = '''<!DOCTYPE html>
... <html>
... <head>
... <title>This is a title</title>
... </head>
... <body>
... <p>Hello world!</p>
... </body>
... </html>'''
如果使用LXML直接,你可以测试例如一些元素的存在,如文档中<div>
或<p>
:
>>> import lxml.html
>>> doc = lxml.html.fromstring(html)
>>> doc.xpath('boolean(//div)')
False
>>> doc.xpath('boolean(//p)')
True
lxml的.xpath()
返回您所期望的:没有<div>
元素,但有<p>
。
如果您将其与Scrapy选择器进行比较,则调用.xpath()
将返回一个Selector
列表。 (这是独立使用布尔表达式或没有的。)
>>> import scrapy
>>> response = scrapy.Selector(text=html)
>>> response.xpath('boolean(//p)')
[<Selector xpath='boolean(//p)' data='1'>]
你需要调用.extract()
或.extract_first()
(或新.get()
快捷方式),以获得“有用的”数据上下工夫。你从.extract()/.extract_first()/.get()
得到的是字符串(S):
>>> response.xpath('boolean(//p)').extract()
['1']
>>> response.xpath('boolean(//p)').extract_first()
'1'
>>> response.xpath('boolean(//p)').get()
'1'
你看到的XPath true
一个'1'
。而且你还可以得到一个'0'
XPath的false
:
>>> response.xpath('boolean(//div)').get()
'0'
在Python,bool()
在非空字符串将返回True
,无论字符串:
>>> bool(response.xpath('boolean(//p)').get())
True
>>> bool(response.xpath('boolean(//div)').get())
True
一个解决办法是使用int()
转换“中”:
>>> bool(int(response.xpath('boolean(//p)').get()))
True
>>> bool(int(response.xpath('boolean(//div)').get()))
False
对于XPath表达式返回的数字,像count(...)
,LXML收益浮动:
>>> doc.xpath('count(//div)')
0.0
>>> doc.xpath('count(//p)')
1.0
尽管Scrapy选择与返回的浮点数的字符串表示:
>>> response.xpath('count(//div)').get()
'0.0'
>>> response.xpath('count(//p)').get()
'1.0'
所以,你想通过提取的字符串到float()
之后对结果进行处理:
>>> float(response.xpath('count(//p)').get())
1.0
>>> float(response.xpath('count(//div)').get())
0.0