1. 程式人生 > >爬蟲學習之路

爬蟲學習之路

高階篇

學會用框架,能站在巨人肩膀上的人,能力往往都不會太差。

這裡我們學習的是PySpider

PySpider環境搭建 (Windows)

  1. pip install pyspider

    安裝pyspider (前面python 已經安裝了2.7)

  2. 下載phantomjs-2.1.1-windows

    加入環境變數,動態載入js會用到

  3. 我們使用mysql儲存

    如果不需要儲存到mysql, 這步可以直接跳過

    安裝mysql,Navicat Premium(db管理工具)

  4. 執行 cmd -> pyspider all

到這裡環境就搭建完成了

Pyspider的基礎

先了解下pyspider的功能:

Pyspider入門實踐 - 定時爬取下載量

下面我們從豌豆莢,百度手機助手,應用寶爬出某個應用的下載量。

code說明:

  • init方法是初始化方法,裡面放了一些url資料,時間等。
  • on_start是入口,相當於main方法
    • @every(minutes=24 * 60) # 每天執行一次
    • @every(minutes=1) # 每min執行一次, 這個一般除錯時用,方便實時檢視情況
  • 頁面解析的三個方法: index_wdjpage, index_baidupage,index_yingyongbaopage
    • @config(age=60) # 有效期1min 一分鐘後才會過期。真正抓的頻率是 on_start的@ every + 這裡的age。即2分鐘才會run一次index_wdjpage
    • @config(priority=3) # priority設定優先順序,數字越高代表最先run到

Code例項

    #!/usr/bin/env python
    # -*- encoding: utf-8 -*-
    # Created on 2017-11-29 16:32:33
    # Project: ZenTalk_Download

    from pyspider.libs.base_handler import *
    import sys
    reload(sys)
    sys.setdefaultencoding('utf-8')
    import uniout
    import re
    import time 

    class Handler(BaseHandler):
        crawl_config = {
        }

        def __init__(self):
            self.wdjurl = 'http://www.wandoujia.com/apps/com.asus.cnzentalk'
            self.baiduurl = 'http://shouji.baidu.com/software/11306355.html'
            self.yingyongbaourl = 'http://sj.qq.com/myapp/detail.htm?apkName=com.asus.cnzentalk'
            self.tool = Tool()
            self.time = self.tool.getCurrentIntTime()

        FILE_NAME = 'zentalk_download.txt'

        #@every(minutes=24 * 60) # 每天執行一次
        @every(minutes=1)  # 每1min執行一次
        def on_start(self):
            self.crawl(self.wdjurl, callback=self.index_wdjpage, fetch_type='js')
            self.crawl(self.baiduurl, callback=self.index_baidupage, fetch_type='js')
            self.crawl(self.yingyongbaourl, callback=self.index_yingyongbaopage, fetch_type='js')

        @config(age=60)  # 有效期1min
        @config(priority=3)
        def index_wdjpage(self, response):
            raw_download = response.doc('[itemprop="interactionCount"]').text()
            download = self.tool.getCount(raw_download)

            # write to file
            self.writeToFile(download, '豌豆莢')

        @config(age=60) # 有效期1min
        @config(priority=2)
        def index_baidupage(self, response):
            raw_download = response.doc('.yui3-g .download-num').text()
            download = self.tool.getCount(re.split(':', raw_download)[1])

            # write to file
            self.writeToFile(download, '百度手機助手')

        @config(age=60)  # 有效期1min
        @config(priority=1)
        def index_yingyongbaopage(self, response):
            raw_download = response.doc('.det-ins-num').text()[:-2]
            download = self.tool.getCount(raw_download)  

            # write to file
            self.writeToFile(download, '應用寶' )

        def writeToFile(self, download, platform, append=True):
            if append :
                f = open(self.FILE_NAME, 'a')
                f.write(platform + ": " + str(download) + '\n') 
            else:
                f = open(self.FILE_NAME, 'w')
                f.write("\n------ time: " + self.tool.getCurrentTime() + "," + str(self.tool.getCurrentIntTime()) + " ------------------\n") 
                f.write(platform + ": " + str(download) + '\n') 
            f.close()

    # 工具類
    class Tool:
        # 將超連結廣告剔除
        removeADLink = re.compile('<div class="link_layer.*?</div>')
        # 去除img標籤,1-7位空格,&nbsp;
        removeImg = re.compile('<img.*?>| {1,7}|&nbsp;')
        # 刪除超連結標籤
        removeAddr = re.compile('<a.*?>|</a>')
        # 把換行的標籤換為\n
        replaceLine = re.compile('<tr>|<div>|</div>|</p>')
        # 將表格製表<td>替換為\t
        replaceTD = re.compile('<td>')
        # 將換行符或雙換行符替換為\n
        replaceBR = re.compile('<br><br>|<br>')
        # 將其餘標籤剔除
        removeExtraTag = re.compile('<.*?>')
        # 將多行空行刪除
        removeNoneLine = re.compile('\n+')

        def replace(self, x):
            x = re.sub(self.removeADLink, "", x)
            x = re.sub(self.removeImg, "", x)
            x = re.sub(self.removeAddr, "", x)
            x = re.sub(self.replaceLine, "\n", x)
            x = re.sub(self.replaceTD, "\t", x)
            x = re.sub(self.replaceBR, "\n", x)
            x = re.sub(self.removeExtraTag, "", x)
            x = re.sub(self.removeNoneLine, "\n", x)
            # strip()將前後多餘內容刪除
            return x.strip()

        # it support convert string include unit to count
        # such as 6000,60.2萬,1億
        def getCount(self, x):
            x = self.replace(x)
            if (self.isFloat(x) or str.isdigit(str(x))):
                return x
            else:
                num = re.findall("\d+\.?\d*", x)[0]
                unit = re.sub(num, "", x)
                unit_number = 1
                if (unit == "萬"):
                    unit_number = 10000
                elif (unit == "億"):
                    unit_number =100000000
                return float(num) * unit_number

        def isFloat(self, number):
            try:
                num = float(number)
                return True
            except ValueError:
                return False

        # 獲取當前時間
        def getCurrentTime(self):
            return time.strftime('[%Y-%m-%d %H:%M:%S]', time.localtime(time.time()))

        # 獲取當前時間 unix 時間戳
        def getCurrentIntTime(self):
            return (int)(time.mktime(time.localtime(time.time())))

Pyspider的Tip

  1. Pyspider的建立的專案都放在下面的位置,以db的形式儲存