從頁面中提取數據的核心技術是HTTP文本解析,在python中常用的模塊處理:
BeautifulSoup 非常流行的解析庫,API簡單,但解析的速度慢。
lxml 是一套使用c語言編寫的xml解析庫,解析速度快,API相對比較復雜。
Scrapy中的Selector類是基於lxml庫建立的,並且簡化了API接口。在使用的過程中先使用xpath或者css選擇器選中頁面中要提取的數據,然后進行提取。
提取數據
調用Selector或者SelectList對象的以下幾種方法可將選中的內容進行提取
extract() 返回選中內容的Unicode字符串。
extract_first() SelectorList專有,返回其中第一個Selector對象調用extract方法。通常SelectorList中只含有一個Selector對象的時候選擇調用該方法。
re() 使用正則表達式來提取選中內容中的某部分。
舉個例子
selector.xpath('.//b/text()') .extract #[‘價格:99.00元’,‘價格:88.00元’,‘價格:88.00元’]
selector.xpath('.//b/text()').re('\d+\.\d+') #[ '99.00','88.00','88.00']
re_first() 返回SelectorList對象中的第一個Selector對象調用re方法。
selector.xpath('.//b/text()').re_first('\d+\.\d+') # '99.00'
實際的開發過程中,幾乎不需要手動創建Selector對象,,Response對象以自身參數自動創建Selector對象
response.xpath('.//h1/text').extract() # [ 'song','shi','chao']
response.css('li::text').extract() # [ 'song','shi','chao']
xpath選擇器
xpath即xml路徑語言,用來確定xml文檔中某個部分的語言,xml文檔(html屬於xml)是一系列節點構成的樹。
基礎語法
/ 選中文檔的根 描述一個從根開始的絕對路徑 ./表示從當前節點選取 (比如提取了一部分,還需要從提取出來里面進行提取就會使用,如果不加 . 會從整個文檔中開始提取)
. 選中當前節點 用來描述相對路徑
.. 選中當前節點的父節點 用來描述相對路徑
ELEMENT 選中子節點中所有的ELEMENT元素節點
//ELEMENT 選中子孫節點中所有的ELEMENT元素節點
* 選中所有元素子節點
text() 選中所有文本子節點
@ATTR 選中名為ATTR的屬性節點
@* 選中所有的屬性節點
[謂語] 謂語用來查找某個特定的節點或者包含某個特定值的節點
舉例
response.xpath('/html/body/div') #選取body下的所有div
response.xpath('//a') #選中文檔所有a
response.xpath('/html/body//div') #選中body下的所有節點中的div,無論在什么位置
response.xpath('//a/text()') #選取所有a的文本
response.xpath('/html/div/*') #選取div的所有元素子節點
response.xpath('//div/*/img') #選取div孫節點的所有img
response.xpath('//img/@src') #選取所有img的src屬性
response.xpath('//a[1]/img/@*') #選取第一個a下img的所有屬性
response.xpath('//a[2]') #所有a中的第2個
response.xpath('//a[last()]') #所有a中的最后一個 ('/a[last()-1]')#倒第二個 ('//a[position()<=3]')#使用position函數選中前三個 ('//div[@id]')#選中所有含有id屬性的div ('//div[@id="song"]')#選中所有id屬性為song的div
response.xpath('//p[contains(@class,'song')]') #選擇class屬性中含有‘song’的p元素
response.xpath('//div/a | //div/p') 或者,頁面中可能是a可能是p
css選擇器
css即層疊樣式表,選擇器不如xpath強大,原理就是選擇的時候翻譯成xpath表達式在調用xpath方法。
* 選擇所有節點
#container 選擇id為container的節點
.container 選擇class包含container的節點
li a 選擇 所有 li 下的所有 a 節點
ul + p 選擇所有ul后面的第一個p元素
#container > ul 選擇id為container的第一個ul節點
a[class] 選取所有有class屬性的a元素
a[href="http://b.com"] 含有href="http://b.com"的a元素
a[href*='job'] 包含job的a元素
a[href^='https'] 開頭是https的a元素
a[href$='cn'] 結尾是cn的a元素
response.css('div a::text').extract() 所有div下所有a的文本
response.css('div a::attr(href)').extract() href的值
response.css('div>a:nth-child(1)') 選中每個div的第一個a > 會設定只在子節點中找,不會到孫節點中
response.css('div:not(#container)') 選取所有id不是container的div
response.css('div:first-child>a:last-child') 第一個div中最后一個a