scrapy使用經驗總結


接着上一篇繼續聊scrapy。

斷斷續續的使用scrapy已經很長時間,在各種問題也算是有所領悟(所需工具firefox,firebug,firefox的xpath插件)。

1. 非標准的html解析問題(上一篇提到過),這個問題蛋疼不是問題有多難解決,而是很難定位到錯誤的原因。在firefox中確保xpath沒有寫錯的情況下,找不到相應的數據,這個時候就要考慮是否是這個原因,直接查看頁面源碼,如果有不標准的html,在firefox中會有紅色標識。

selector = XPathSelector(text=response.body.replace('<div class="left-clear"/>','<div class="left-clear">'))

 

2. 通常的情況下,一些流量比較大的網站都有反爬蟲的機制,避免惡意的訪問,減輕服務器的壓力。一般的情況的下調整抓取的間隔,更換代理。2種方式都有缺點。

  抓取間隔設置download_delay=1,通常設置這個屬性,整個spider的性能變得非常低。

  更換代理,可以到http://pachong.org/去找免費的代理,一般速度也不快,而且不穩定。

 

3. http code欺騙(我自己取得名字),一般情況數據的正常返回都是20x,scrapy會自動忽略掉50x的http code。這個(http://www.travelplus.cn/plus/list.php?tid=8

)用瀏覽器打開的時候,你看不出任何問題。用firebug就能清晰的看到,其實它是將500頁面,當做正常頁面顯示。

  在spider里添加handle_httpsatstus_code = [500],一切照舊即可。

 

4. 模擬瀏覽器請模擬徹底。如果你有服務器點開發的經驗,就不難理解,服務器可以通過任何一個headers或者參數來屏蔽你的request。參數自然不用說,能帶上都帶上,至於一些參數加密,以后再提。主要是針對headers中的幾個常用的。

  Cookie,這個最常見用的,平心而論scrapy對cookie的支持只是基礎的支持,用起來不太好用。

  User-Agent, 這個主要還是服務器為了區分request是來自pc端還是手機端,會導致response不一樣。

  Referer, 防止偽造的跨網站請求。

  X-Requested-With=XMLHttpRequest, 這個很好理解,對於同一個url,ajax request和普通request的response結果不一樣很正常

  Content-Length, 一些網站沒有這個header會返回411

  以上5個header基本上能解決問題,萬一遇到頑固份子,那只好徹底的模仿吧。

 

5. 不要忽略firebug里監控到任何http request,部分網站在提交數據的時候,會先跳轉到一個頁面,這個頁面是空白的頁,只是包含一些隱藏的表單,最后用js帶上表單跳轉到其他的頁面。因此在firebug的監控的request中,會莫名其妙的多出來一些參數。

 

6. xpath表達式,能簡單盡量簡單,盡量class和id來表達。千萬別將xpath的表達式依賴很多屬性,這樣難以維護不說,而且極不穩定。

 

7. xpath表達式能在瀏覽器中找到元素,在spider里確不能,有可能性js動態加載,還有table元素,有的會自動添加th等。這個時候請直接對着html源碼寫你的表達式。

 

8. ajax request和json,這應該是現在網站的主流。要關注的真正得到數據的request,通常我們要抓取的數據也都在ajax request中,拿到數據后用json.loads(response.body)

 

9. 要抓取的內容分布在不同的request中,這個時候request meta就能很好的勝任。

def parse_city_item(self, response):
        x = HtmlXPathSelector(response)
        item = Item()
        //給item賦值
        item['title'] = ''.join(x.select('//div[@class="title"]/text()').extract())
        data = {}
        req = FormRequest(url=url,formdata=data,callback=self.parse_comment)
        req.meta['item'] = item
        //帶上返回req
        return req
def parse_comment(self, response):
        item = response.request.meta['item']
        x = HtmlXPathSelector(response)
        item['content'] = ''.join(x.select('//div[@class="content"]/text()').extract())
        return item
        

 

10. 增量抓取,很多情況下需要抓取網站更新的內容。我們知道在一次抓取的過程是能避免重復抓取,scrapy默認提供文件存儲的方式,只需要再settings里設置JOBDIR="path"。我在使用scrapy還是0.9,沒有這個特性,使用redis作為url存儲。個人感覺對於大規模抓取用redis還是比文件的方式要好很多。redis里可以設置key的過期時間,肯定會有人說,這樣能保證不重復的抓取嗎,當然不能絕對,但是可以調整抓取深度,對於抓取較為頻繁網站,抓取到相同的概率就很低。比如說抓取sina的體育新聞,將url做md5加密存儲到redis里,過期時間設置為1天,抓取體育新聞滾動頁面前3頁(http://roll.sports.sina.com.cn/s/channel.php?ch=02#col=64&spec=&type=&ch=02&k=&offset_page=0&offset_num=0&num=60&asc=&page=1),15分鍾抓取一次。而單純用文件方式存儲的話,文件只大不小,多了自然影響性能。

 

11. 編碼,上一篇也提到過。scrapy為我們做了編碼,但是如果這樣好錯了,就需要特殊處理了。

 

 

 

 

 

 

 

 

 

 

 

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM