請注意:基於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