基於python2.7版本,爬取百度手機小幫手(http://shouji.baidu.com/software/)網站中app的資料。 一、爬取程式流程圖
爬蟲程式流程圖如下: Created with Raphaël 2.1.0 開始 分析地址結構 獲得app類別頁的url 爬取app詳情頁url 爬取App詳情頁的資料 將爬取資料儲存到json檔案 結束 二、具體步驟 1.分析url地址結構
進入百度手機小幫手網站http://shouji.baidu.com/software/後,可以看到共分為十個類別:社交通訊、系統工具、理財購物等等,可以知道通過這十個類別分別爬取app的資料,應該就可以全部完整的爬取到所有app。
隨意點擊一個類別進入後,如點擊社交通訊這一大類,看到url是:http://shouji.baidu.com/software/503/,分析可以知道這十個類別分別是501~510,即url就是shouji.baidu.com/software/再加上501~510中的一個數字。
每個類別頁都有1-8頁不等的app,比如社交通訊類app的第二頁就是http://shouji.baidu.com/software/503/list_2.html,也就是在list_後面加上數字1-8即可。
經過以上的分析,可以將爬取的url分為以下的三部分結構:
self.base_URL = 'http://shouji.baidu.com/software/'self.category_num = [501, 502, 503, 504, 505, 506, 507, 508, 509, 510]self.page_num = [1, 2, 3, 4, 5, 6, 7, 8]
其中category_num和page_num分別代表類別數字和分頁編號。 2.獲得所有app類別頁的url
定義數組categoryPageURL_list進行類別頁拼接後url的儲存:
def getAppCategoryPageURL(self): #所有應用類別的URLlist categoryPageURL_list = [] for x in self.category_num: for y in self.page_num: categoryPageURL_list.append(self.base_URL + str(x) + '/list_' + str(y) + '.html') return categoryPageURL_list
3.爬取所有app詳情頁的url
進行所有app詳情頁url 的爬取,並將其儲存在appDetailPageURL_list數組中。
#爬取所有應用 詳情 頁的urldef getAppDetailPageURL(self): categoryPageURL_list = self.getAppCategoryPageURL() appDetailPageURL_list = [] for url in categoryPageURL_list: #構造request請求對象 request = urllib2.Request(url) response = urllib2.urlopen(request) content = response.read().decode("unicode-escape") #re模組用於對Regex的支援,pattern可以理解為一個匹配模式,re.S指"."可以匹配換行"\n" pattern = re.compile('<div.*?app-box">.*?<a href="(.*?)".*?>', re.S) resultStr = re.findall(pattern, content) for result in resultStr: #print 'crawling ' + result appDetailPageURL = 'http://shouji.baidu.com/' + result appDetailPageURL_list.append(appDetailPageURL) return appDetailPageURL_list
4.爬取App詳情頁的資料
對App詳情頁的內容進行爬取,得到app的具體資料。
#爬取App詳情頁中的所需內容def getAppInfo(self, appURL): try: request = urllib2.Request(appURL) response = urllib2.urlopen(request) except urllib2.URLError, e: print "Get appInfo failed:", e.reason return None content = response.read().decode("utf-8") # 建立儲存結果的dict result = {} #得到app名字 pattern = re.compile('<span>(.*?)</span>') resultStr = re.search(pattern, content) if resultStr: result['Name'] = resultStr.group(1) # 得到app大小,需要對字串處理 pattern = re.compile('<span class="size">(.*?)</span>') resultStr = re.search(pattern, content) if resultStr: result['Size'] = (((resultStr.group(1)).split(':'))[1]).strip() #版本 pattern = re.compile('<span class="version">(.*?)</span>') resultStr = re.search(pattern, content) if resultStr: result['Version'] = (((resultStr.group(1)).split(':'))[1]).strip() #下載量 pattern = re.compile('<span class="download-num">(.*?)</span>') resultStr = re.search(pattern, content) if resultStr: result['download-num'] = (((resultStr.group(1)).split(':'))[1]).strip() #LOGO URL pattern = re.compile('<img src="(.*?)".*?/>') resultStr = re.search(pattern, content) if resultStr: result['app-pic'] = resultStr.group(1) #下載地址 pattern = re.compile('<div.*?area-download">.*?<a target="_blank.*?href="(.*?)".*?>', re.S) resultStr = re.search(pattern, content) if resultStr: result['app-href'] = resultStr.group(1) #詳情頁 result['page-url'] = appURL #應用描述 pattern = re.compile('<p.*?content content_hover">(.*?)<span.*?>.*?</span></p>', re.S) resultStr = re.search(pattern, content) if resultStr: result['description'] = resultStr.group(1) else: pattern = re.compile('<div class=.*?brief-long">.*?<p.*?content">(.*?)</p>.*?</div>', re.S) resultStr = re.search(pattern, content) if resultStr: result['description'] = resultStr.group(1) #應用截圖 pattern = re.compile('<li><img data-default=.*?src="(.*?)".*?>', re.S) resultStr = re.search(pattern, content) if resultStr: result['screen-shot'] = resultStr.group(1) #print result return result
5.將爬取資料儲存到json檔案
在此方法中將所有爬取的資料儲存到appData.json檔案中。
#將資料儲存到jsondef saveData(self, resultInfo): # resultInfo轉換為json資料格式進行儲存 encodedjson = json.dumps(resultInfo) with open('appData.json', 'w') as f: f.write(encodedjson) print 'Finished.'
我將所有的方法及參數封裝到Spider類中,建立爬蟲的開始入口,整體代碼如下:
# -*- coding:utf-8 -*-import urllib2import reimport jsonclass AppSipder: def __init__(self): #URL模式:http://shouji.baidu.com/software/502/list_x.html,分成三個部分 self.base_URL = 'http://shouji.baidu.com/software/' #類別數字 #self.category_num = [501, 502, 503, 504, 505, 506, 507, 508, 509, 510] self.category_num = [501] #分頁編號 #self.page_num = [1, 2, 3, 4, 5, 6, 7, 8] self.page_num = [1] #獲得所有應用 類別 頁的url def getAppCategoryPageURL(self): #所有應用類別的URLlist categoryPageURL_list = [] for x in self.category_num: for y in self.page_num: categoryPageURL_list.append(self.base_URL + str(x) + '/list_' + str(y) + '.html') return categoryPageURL_list #爬取所有應用 詳情 頁的url def getAppDetailPageURL(self): categoryPageURL_list = self.getAppCategoryPageURL() appDetailPageURL_list = [] for url in categoryPageURL_list: #構造request請求對象 request = urllib2.Request(url) response = urllib2.urlopen(request) content = response.read().decode("unicode-escape") #re模組用於對Regex的支援,pattern可以理解為一個匹配模式,re.S指"."可以匹配換行"\n" pattern = re.compile('<div.*?app-box">.*?<a href="(.*?)".*?>', re.S) resultStr = re.findall(pattern, content) for result in resultStr: #print 'crawling ' + result appDetailPageURL = 'http://shouji.baidu.com/' + result appDetailPageURL_list.append(appDetailPageURL) return appDetailPageURL_list #爬取App詳情頁中的所需內容 def getAppInfo(self, appURL): try: request = urllib2.Request(appURL) response = urllib2.urlopen(request) except urllib2.URLError, e: print "Get appInfo failed:", e.reason return None content = response.read().decode("utf-8") # 建立儲存結果的dict result = {} #得到app名字 pattern = re.compile('<span>(.*?)</span>') resultStr = re.search(pattern, content) if resultStr: result['Name'] = resultStr.group(1) # 得到app大小,需要對字串處理 pattern = re.compile('<span class="size">(.*?)</span>') resultStr = re.search(pattern, content) if resultStr: result['Size'] = (((resultStr.group(1)).split(':'))[1]).strip() #版本 pattern = re.compile('<span class="version">(.*?)</span>') resultStr = re.search(pattern, content) if resultStr: result['Version'] = (((resultStr.group(1)).split(':'))[1]).strip() #下載量 pattern = re.compile('<span class="download-num">(.*?)</span>') resultStr = re.search(pattern, content) if resultStr: result['download-num'] = (((resultStr.group(1)).split(':'))[1]).strip() #LOGO URL pattern = re.compile('<img src="(.*?)".*?/>') resultStr = re.search(pattern, content) if resultStr: result['app-pic'] = resultStr.group(1) #下載地址 pattern = re.compile('<div.*?area-download">.*?<a target="_blank.*?href="(.*?)".*?>', re.S) resultStr = re.search(pattern, content) if resultStr: result['app-href'] = resultStr.group(1) #詳情頁 result['page-url'] = appURL #應用描述 pattern = re.compile('<p.*?content content_hover">(.*?)<span.*?>.*?</span></p>', re.S) resultStr = re.search(pattern, content) if resultStr: result['description'] = resultStr.group(1) else: pattern = re.compile('<div class=.*?brief-long">.*?<p.*?content">(.*?)</p>.*?</div>', re.S) resultStr = re.search(pattern, content) if resultStr: result['description'] = resultStr.group(1) #應用截圖 pattern = re.compile('<li><img data-default=.*?src="(.*?)".*?>', re.S) resultStr = re.search(pattern, content) if resultStr: result['screen-shot'] = resultStr.group(1) #print result return result #爬蟲開始入口 def startSpider(self): print 'Start crawling please wait...' appDetailPageURL_list = self.getAppDetailPageURL() resultInfo = [] for url in appDetailPageURL_list: resultInfo.append(self.getAppInfo(url)) print len(resultInfo), 'apps have been crawled.' #resultInfo轉換為json資料格式進行儲存 encodedjson = json.dumps(resultInfo) with open('appData.json', 'w') as f: f.write(encodedjson) print 'Finished.'Spider = AppSipder()Spider.startSpider()