筆者最近對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 將此賦值給它就能完成傳輸了