筆者最近對scrapy的學習可謂如火如荼,雖然但是,即使是一整天地學習下來也會有中間兩三個小時的“無效學習”,不是筆者開小差,而是掉進了深坑出不來。
在此,給各位分享一下作為一名Scrapy框架的初學者,筆者在學習過程中遇到的各個大坑和小技巧吧。
1. user_agent
這個,在某些網站看來這無關要緊(比如筆者的網站—— 程式碼的邊城 ),但對某些設定了反爬機制的網站來說,這是你的蜘蛛開門遇到的攔路虎。如果沒有提前設定好這個引數,那你的蜘蛛連網站都進不去。
不僅網站進不去,而且它還不報錯。試問,一個滿心壯志,準備在網際網路上靠他的蜘蛛大展巨集圖的人,如果遇到了這樣的事,那將是多麼的心灰意冷。所以,筆者在這裡分享之前的文章,有對此的解決方案,歡迎瀏覽 點此跳轉
2. ROBOTSTXT_OBEY
跟上面的user_agent一樣,這也是一個在settings.py裡面設定好的引數值。我們通過scrapy固定語句新建專案後就會發現,settings.py裡面這條被點亮的,且預設值為True的語句。
這意味著我們的Spider會遵守robots.txt的規則。 簡單來說,robots.txt 是遵循 Robot 協議的一個檔案,它儲存在網站的伺服器中,它的作用是,告訴搜尋引擎爬蟲,本網站哪些目錄下的網頁不希望你進行爬取收錄。在Scrapy啟動後,會在第一時間訪問網站的 robots.txt 檔案,然後決定該網站的爬取範圍。
但我們的爬蟲一般來說都沒什麼節操,也知道不會怎麼遵守這條語句,所以在新建好專案的時候,我們就直接把這個配置,設定為False!直接在遇到問題前解決問題!
3. allowed_domains
在我們新建好專案之後,會在你的爬蟲檔案裡出現這條語句
start_urls 一般指的是你的Spider的初始連結,是蜘蛛帝國最開始的基石,allowed_domains就是你蜘蛛帝國最外面的圍欄。有一種說法是,scrapy的spider爬取速度特別快,所以為了防止它亂爬到其他介面,我們會在這裡設定allowed_domains。設定好後,不屬於此範圍的域名就會被過濾,我們的蜘蛛也會被好好關在設定好的域名裡。
但一個弊端是,這條語句的存在感不強。有時候,我們在寫多介面爬蟲的時候特別起勁,往往會忘了最開始設定好的域名範圍,而我們在進行多頁面的資料提取時,很有可能會需要跳出你原來設定好的這個域名,進入其他的域名裡提取資料。這時候,這個allowed_domains就成為了我們的絆腳石,如果你忘了它的存在,你會很絕望地發現,你新寫的parse函式竟然無法呼叫下一個介面的資料,而且它還 不!報!錯!
解決方法:就是在allowed_domains裡新增新的域名,共同作為爬蟲爬取的範圍
4. tbody 和 font
在筆者寫到跟tbody有關的xpath之前,筆者已經知道這個坑了,於是完美避過。如果你還不清楚,可以聽筆者細細分析。
我們寫xpath路徑時,往往都是先找到一個css選擇器,然後描寫他的路徑
比如我們要在瀏覽器除錯介面獲取選中的這個td:
xpath = "//table[@class = 'present-table']/tr[1]/td[2]/text()"
複製程式碼
以上是筆者分享的正確的寫法之一,我們在瀏覽器的response裡面就可以找到相同的xpath與此對應
你看,是沒有 這個標籤的,我們的xpath按照response的寫法才是正確的,只是一般來是開啟瀏覽器除錯介面過去xpath最方便而已。對此,筆者去搜錄了一下原因。
並不是全部的 都無法解析,如果在原始碼裡面寫入了 那我們原來的方法還是可行的。但原始碼沒有寫入的話,瀏覽器為了規範化,會自動在新增這個標籤,我們寫xpath的時候就要跳過這個標籤。
目前筆者瞭解到,還有這一特性的標籤還有 ,也需要注意。
5. 圖片網址@src必須是列表格式
這又是筆者早早避過的坑,特此分享避坑經驗。
這是大家約定俗稱的一種寫法,筆者也講不出具體原理。對於@src的寫法,筆者這裡主要分享兩種寫法
# 第一種
src = response.xpath('//img/@src').extract()
# 第二種
src = [response.xpath('//img/@src').extract_first()]
複製程式碼
以上運用了extract()和extract_first()本身的特性
extract():這個方法返回的是一個陣列list,裡面包含了多個string,如果只有一個string,則返回['ABC']這樣的形式。
extract_first():這個方法返回的是一個string字串,是list陣列裡面的第一個字串。
筆者自身傾向於第一種寫法,寫法簡潔,同時能應對多個img的情況
* 小技巧——多介面資料如何傳輸
有時候我們爬蟲裡面的item,他的同類資料分佈在各個網頁之中,那麼我們就需要 request.meta 來儲存上一個parse中的item資料
我們從當前頁面呼叫下一個頁面時,使用如下的語句
yield scrapy.Request(the_href,callback=self.another_parse,meta={"item":item})
複製程式碼
就能成功的把我們的 item 傳送到 another_parse 中去,以response.meta的形式存在,然後在這裡重新定義一個 item 將此賦值給它就能完成傳輸了