1. 程式人生 > >使用python爬蟲爬取百度手機助手網站中app的資料

使用python爬蟲爬取百度手機助手網站中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陣列中。

#爬取所有應用 詳情 頁的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模組用於對正則表示式的支援,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檔案中。

#將資料儲存到json
def 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 urllib2
import re
import json

class 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模組用於對正則表示式的支援,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()