實現一個爬蟲的關鍵鸯旁,我理解下來有兩點:
一是url分析噪矛,就是從哪里進入,經過哪些路徑(列表頁铺罢,分頁)艇挨,新增url在哪里添加,這些關系到一個數據完整的鏈路韭赘。
二是頁面源代碼分析缩滨,解析出需要的數據(包括一個完整的數據在哪幾個頁面上獲取)泉瞻。主要弄清文檔結構脉漏,數據的選取點放在哪里。
搞清楚這兩個要點后袖牙,實現一個爬蟲的功能不難侧巨,無論是采用Scrapy框架,還是用Python+正則鞭达,或BeautifulSoup的方式司忱。
下面嘗試從一個案例來分析,使用Scrapy框架如何規(guī)劃url畴蹭,最終拿到要解析的數據坦仍。
先從要抓取的數據和最終頁面來分析URL
簡書的用戶首頁的url是這樣的http://www.reibang.com/users/54b5900965ea/
,即/users+ 用戶ID叨襟,但是不同類型的用戶看到用戶首頁是不一樣的繁扎,同樣是/users/userId進來的,發(fā)表過文章的用戶的首頁指向的是http://www.reibang.com/users/54b5900965ea/latest_articles
即最新文章頁面(latest_articles), 沒發(fā)表文章的用戶(包括點贊糊闽、評論梳玫、粉)指向的頁面是http://www.reibang.com/users/useridxxxx/timeline
,即最新動態(tài)頁面(timeline)
這兩種頁面上都有我們所需要的信息墓怀,左邊都是個人信息+發(fā)表文章匯總數據汽纠,互動數據。如果我們要獲得用戶的注冊時間傀履,一共發(fā)表多少評論(這算一個用戶活躍數據),這兩個數據只能在timeline(最新動態(tài))頁面上獲取。
為什么要分析url钓账,是因為爬蟲要解析頁面碴犬,如果同一個入口,對應兩個不同的頁面梆暮,程序在運行時服协,就也不能決定下一步怎么走,增加了程序編寫的復雜度啦粹。所以我在抓取用戶數據時偿荷,把獲取用戶數據的頁面定為timeline頁。注意唠椭,要獲取用戶注冊時間跳纳,在timeline的最后一頁。所以timeline的最后一頁贪嫂,我們開始解析數據寺庄。
評論數就比較麻煩,需要在每一頁上進行統計力崇,在timeline最后一頁匯總斗塘,提交item。
如何拿到分頁的URL亮靴?
基本上分頁有兩種處理方式:
1)知道總記錄數馍盟,每頁記錄條數,那就能很快構造一個url茧吊,一個循環(huán)就能解決贞岭,也能快速定位到最后一頁獲取數據。
獲取一個特征用戶的粉絲url (之后用于構造用戶的最新動態(tài)頁timeline)饱狂,就是采用的這種方法曹步。
2)無法知道總記錄數,頁面和源代碼中均沒有休讳。一般這種分析是通過一個“加載更多”按鈕來提交下一頁的url讲婚,url參數中常有maxid和其他看似奇怪的參數,不是通常的page=n這種俊柔。
在簡書首書的熱門文章分頁筹麸,用戶的最新動態(tài)分頁,都是這種方式雏婶。方法就是解析出分頁對應的url, 再進行遞歸調用即可物赶。
怎樣知道是哪一種分頁方式,用chrome的元素審查功能留晚,打開network加載下一頁時查看url酵紫,并結合源代碼進行分析,即可搞定。
分析一下爬蟲運行時URL規(guī)劃
即如何從爬蟲入口URL到解析數據的頁面奖地。
1橄唬、待爬取的URL放在start_urls
列表中,爬蟲啟動后parse()會依次從該列表中處理每一個url参歹。列表中放的是大咖的粉絲頁url仰楚,即 /users/useridxxx/followers
# 獲取粉絲分頁信息 進口url followers, 出口followers分頁url
def parse(self, response):
selector = Selector(response)
fnum = selector.xpath('/html/body/div[4]/div[2]/ul/li[3]/a/text()').extract()[0]
fnum = filter(str.isdigit, str(fnum))
pages = int(fnum) / 9 + 1
t = int(time.time())
for i in range(1, pages + 1):
nurl = response.url + '?_' + str(t) + '&page=' + str(i)
yield Request(nurl,callback=self.parse_user_url)
這時要進行分頁處理,即拿到粉絲分頁的所有url犬庇,接下來從這個url解析出用戶的首頁僧界。轉去調用 parse_url()方法。
2臭挽、parser_url()方法捂襟,入口的url是分頁的follower頁面,目標是解析數據后拿到用戶url埋哟, 再構造出最態(tài)動態(tài)url, 出口的url是/users/usridxxx/timeline笆豁,再去調用parse_user_detail()方法。
#獲取用戶timeline 進口url followers ,出口url timeline
def parse_user_url(self,response):
selector = Selector(response)
users = selector.xpath('//ul[@class="users"]/li/a/@href').extract()
for user in users:
userurl = 'http://www.reibang.com' + user + '/timeline'
yield Request(userurl, callback=self.parse_user_detail)
3赤赊、parse_user_detail()完成最終的數據解析闯狱。
注意,此時timeline需要分頁處理抛计,這里也需要遞歸調用哄孤。還涉及到Request之間傳遞參數,最終一個用戶完整的信息是在多個頁面獲取的吹截。
yield Request(url, meta={'comments':comment},callback=self.parse_user_detail)
至此瘦陈,一個完整爬蟲url分析完畢,代碼實現基本可以一氣呵成波俄。