1. 因為使用的yield,而不是return。parse函數將會被當做一個生成器使用。scrapy會逐一獲取parse方法中生成的結果,並判斷該結果是一個什么樣的類型;
2. 如果是request則加入爬取隊列,如果是item類型則使用pipeline處理,其他類型則返回錯誤信息。
3. scrapy取到第一部分的request不會立馬就去發送這個request,只是把這個request放到隊列里,然后接着從生成器里獲取;
4. 取盡第一部分的request,然后再獲取第二部分的item,取到item了,就會放到對應的pipeline里處理;
5. parse()方法作為回調函數(callback)賦值給了Request,指定parse()方法來處理這些請求 scrapy.Request(url, callback=self.parse)
6. Request對象經過調度,執行生成 scrapy.http.response()的響應對象,並送回給parse()方法,直到調度器中沒有Request(遞歸的思路)
7. 取盡之后,parse()工作結束,引擎再根據隊列和pipelines中的內容去執行相應的操作;
8. 程序在取得各個頁面的items前,會先處理完之前所有的request隊列里的請求,然后再提取items。
下面是利用parse函數循環爬取多個頁面的一個實例:
繼續上次的例子,上次的爬蟲代碼中只爬取了一個頁面的內容,如果想要爬取多個鏈接的內容,可以在每個頁面的下一頁這個標簽中來獲取它的鏈接,並且在parse()函數中生成一個request,存入爬取隊列,在通過得到的一個又一個的response對象來獲取頁面信息,生成item,再將item傳給pipelines進行數據的儲存。
下面貼上爬蟲的代碼:
# -*- coding: utf-8 -*- import scrapy from sc.items import ScItem class QsbkSpiderSpider(scrapy.Spider): name = 'qsbk_spider' #allowed_domains = ['http://www.lovehhy.net'] start_urls = ['http://www.lovehhy.net/Default.aspx'] baseUrl = "http://www.lovehhy.net" def parse(self, response): node_title_list = response.xpath("//div[@class='post_recommend_new']/h3/a/text()").extract() node_time_list = response.xpath("//div[@class='post_recommend_new']/div[@class='post_recommend_time']/text()").extract() items = [] for i in range(len(node_title_list)): item = ScItem() title = node_title_list[i] time = node_time_list[i] item = ScItem(title=title, time=time) # 產生item yield item # 提取下一頁的li標簽 next_url = response.xpath("//div[@id='dig_lcpage']/div[@id='ct_page']/ul/li[last()]/a/text()").extract()[0] # print("是否下一頁的位置是%s" ,str(next_url)) # 提取待拼接的分頁部分字符串 url_pae = response.xpath("//div[@id='dig_lcpage']/div[@id='ct_page']/ul/li[last()]/a/@href").extract() print(url_pae) if "下一頁" in next_url: real_url = self.baseUrl + url_pae[0] print(real_url) yield scrapy.Request(real_url, callback=self.parse) else: return
爬好的數據: