關於Scrapy crawlspider rules的規則——翻頁
最近在學習爬蟲,對於crawlspider rules的執行機制有點疑問,於是自己研究了一下,總結出以下幾點:
1、rules裡的Rule規則執行是有順序的,按照由上往下執行;
2、request url的獲取是Rule定位到的容器裡,所有a標籤裡的href連結,比如用xpath定位
rules = (
Rule(LinkExtractor(restrict_xpaths=("//div/ul")),callback='parse_item'),
)
則在ul容器下的所有a標籤的連結全都會被獲取到,並且侍自動傳送請求,不用自己手動傳送請求;
3、響應頁面是Rule請求的連結的頁面內容,也就是你定位容器ul裡的a標籤的連結,然後你用滑鼠點選該連結所看到的頁面內容,在callback函式裡提取資料也是在這個頁面裡提取,parse_item(self,response),這個函式的response物件就是這個頁面內容,千萬不要搞錯物件了;
4、follow,這個引數開始把我搞得有點暈,follow就是跟進的意思,如果follow=True,那麼,在你獲取到的響應頁面裡,所以符合Rule規則的href連結都會被獲取到,而且它還會自動跟進,進入到獲取到的連結響應頁面,在該頁面又一次匹配Rule規則,看看有沒有符合的,如果有又繼續跟進,一直到匹配不到規則為止。舉個例子:
rules = (
Rule(LinkExtractor(restrict_xpaths=("//div/ul")),follow=True),
)
那麼首先,該規則會獲取當前頁面符合Rule規則的所有a連結,當前頁面就是start_urls頁面,比如獲取到的連結為
<a class='dd_first ' href="http://book.dangdang.com/textbook?biaoti" target="_blank" title="教材" nname="book-65152-9163_1-468598_2" ddt-src="http://book.dangdang.com/textbook?biaoti">教材</a>
它會繼續進入這個href連結的頁面,然後繼續再匹配Rule規則,看看還有沒有符合的連結,就相當於你在響應頁面的elements裡面查詢到符合規則的a標籤url之後,再點選這個url,再在這個頁面的elements裡查詢還有沒有符合Rule規則的href連結,如此迴圈,直到找不到符合Rule規則為止;
5、如果Rule規則裡有callback="parse_item",follow=True,那麼情況就會比較複雜,你可以想像獲取到一個響應頁面符合Rule規則的連結,然後呼叫函式,在這個頁面再去follow其它的目標連結,再呼叫函式,用xpath定位會相對好一點,如果用allow=(r'')正則表示式匹配,會相對混亂點,適當的情況下也會這樣子用,但是比較少吧,可以自己測試體驗一下。
6、翻頁,翻頁有兩種情況
第一種情況(start_url的響應頁面下方有翻頁連結):
在rules裡定義兩條Rule規則,一條是獲取響應頁面規則,一條是獲取翻頁連結規則,翻頁的規則跟在獲取響應頁面規則下面,順序不要搞錯了,如下:
rules = (
Rule(LinkExtractor(allow=r'/web/site0/tab5240/info\d+\.htm'), callback='parse_item'),
Rule(LinkExtractor(allow=r'http://bxjg.circ.gov.cn/web/site0/tab5240/module14430/page\d\.htm'),follow=True),
)
第二種情況(start_url的響應頁面下方沒有翻頁連結,要進入a 標籤連結才有翻頁連結):
這種情況下,就不能在rules定義翻頁規則了,因為即使定義了翻頁規則,也找不到,因為rules裡面的所有規則,第一次獲取響應頁面都是對應start_url地址的內容,在這個頁面上沒有符合Rule規則的,就找不到了,這裡我也不多說了,直接去原始碼吧!
class TestSpider(CrawlSpider):
name = 'test'
allowed_domains = ['dangdang.com']
start_urls = ['http://book.dangdang.com/']
rules = (
Rule(LinkExtractor(restrict_xpaths=("//div[@class='conflq_body']/div[@name='m403752_pid5438_t10274']//div/dl[@ddt-area='5358']/dd")), callback='parse_item'),
)
def parse_item(self, response):
item={}
item['cate_0']=''
item['cate_1'] = ''
item['cate_2'] = ''
item['cate_3'] = ''
breadcrum=response.xpath("//div[@class='crumbs_fb_left']/div[@class='select_frame']/a[@name='breadcrumb-category']/text()").getall()
for i in range(len(breadcrum)):
item['cate_{}'.format(i)]=breadcrum[i]
book_li=response.xpath("//div[@id='search_nature_rg']/ul/li")
for li in book_li:
item['book_title']=li.xpath(".//p[@class='name']/a/@title").get()
item['book_price']=li.xpath(".//p[@class='price']/span/text()").get()
item['book_url']=li.xpath(".//p[@class='name']/a/@href").get()
book_search=li.xpath(".//p[@class='search_book_author']/span")
item['book_author']=book_search[0].xpath(".//a/@title").get()
item['public_date']=book_search[1].xpath(".//text()").get()
item['public_date']=re.sub("/",'',item['public_date']) if item['public_date'] else None
item['public_company']=book_search[2].xpath(".//a/@title").get()
yield item
next_page_url=response.xpath("//div[@class='paging']//li[@class='next']/a/@href").get()
next_page="http://category.dangdang.com"+next_page_url
yield scrapy.Request(next_page,callback=self.parse_item)
這種情況下的翻頁要在函式裡面進行,在parse_item()函式的最後三行,是翻頁語句!自己可以測試一下,我也不知道rules規則能不能有其它方法可以做到,反正我現在沒發現,如果有朋友知道的可以告訴一下!
以上是我自己的個人觀點,如有錯漏煩請指出!