爬蟲學(xué)習(xí)之一個簡單的網(wǎng)絡(luò)爬蟲

概述


這是一個網(wǎng)絡(luò)爬蟲學(xué)習(xí)的技術(shù)分享,主要通過一些實際的案例對爬蟲的原理進行分析,達到對爬蟲有個基本的認(rèn)識,并且能夠根據(jù)自己的需要爬到想要的數(shù)據(jù)。有了數(shù)據(jù)后可以做數(shù)據(jù)分析或者通過其他方式重新結(jié)構(gòu)化展示。

什么是網(wǎng)絡(luò)爬蟲


網(wǎng)絡(luò)爬蟲(又被稱為網(wǎng)頁蜘蛛,網(wǎng)絡(luò)機器人,在FOAF社區(qū)中間,更經(jīng)常的稱為網(wǎng)頁追逐者),是一種按照一定的規(guī)則,自動地抓取萬維網(wǎng)信息的程序或者腳本。另外一些不常使用的名字還有螞蟻、自動索引、模擬程序或者蠕蟲。via 百度百科網(wǎng)絡(luò)爬蟲

網(wǎng)絡(luò)蜘蛛(Web spider)也叫網(wǎng)絡(luò)爬蟲(Web crawler)[1],螞蟻(ant),自動檢索工具(automatic indexer),或者(在FOAF軟件概念中)網(wǎng)絡(luò)疾走(WEB scutter),是一種“自動化瀏覽網(wǎng)絡(luò)”的程序,或者說是一種網(wǎng)絡(luò)機器人。它們被廣泛用于互聯(lián)網(wǎng)搜索引擎或其他類似網(wǎng)站,以獲取或更新這些網(wǎng)站的內(nèi)容和檢索方式。它們可以自動采集所有其能夠訪問到的頁面內(nèi)容,以供搜索引擎做進一步處理(分檢整理下載的頁面),而使得用戶能更快的檢索到他們需要的信息。via 維基百科網(wǎng)絡(luò)蜘蛛

以上是百度百科和維基百科對網(wǎng)絡(luò)爬蟲的定義,簡單來說爬蟲就是抓取目標(biāo)網(wǎng)站內(nèi)容的工具,一般是根據(jù)定義的行為自動進行抓取,更智能的爬蟲會自動分析目標(biāo)網(wǎng)站結(jié)構(gòu)類似與搜索引擎的爬蟲,我們這里只討論基本的爬蟲原理。

爬蟲工作原理


網(wǎng)絡(luò)爬蟲框架主要由控制器解析器索引庫三大部分組成,而爬蟲工作原理主要是解析器這個環(huán)節(jié),解析器的主要工作是下載網(wǎng)頁,進行頁面的處理,主要是將一些JS腳本標(biāo)簽、CSS代碼內(nèi)容、空格字符、HTML標(biāo)簽等內(nèi)容處理掉,爬蟲的基本工作是由解析器完成。所以解析器的具體流程是:

入口訪問->下載內(nèi)容->分析結(jié)構(gòu)->提取內(nèi)容

分析爬蟲目標(biāo)結(jié)構(gòu)


這里我們通過分析一個網(wǎng)站[落網(wǎng):http://luoo.net] 對網(wǎng)站內(nèi)容進行提取來進一步了解!

第一步 確定目的
抓取目標(biāo)網(wǎng)站的某一期所有音樂

第二步 分析頁面結(jié)構(gòu)
訪問落網(wǎng)的某一期刊,通過Chrome的開發(fā)者模式查看播放列表中的歌曲,右側(cè)用紅色框線圈出來的是一些需要特別注意的語義結(jié)構(gòu),見下圖所示:

以上紅色框線圈出的地方主要有歌曲名稱,歌曲的編號等,這里并沒有看到歌曲的實際文件地址,所以我們繼續(xù)查看,點擊某一個歌曲就會立即在瀏覽器中播放,這時我們可以看到在Chrome的開發(fā)者模式的Network中看到實際請求的播放文件,如下圖所示:

根據(jù)以上分析我們可以得到播放清單的位置和音樂文件的路徑,接下來我們通過Python來實現(xiàn)這個目的。

實現(xiàn)爬蟲


Python環(huán)境安裝請自行Google

主要依賴第三方庫

Requests(http://www.python-requests.org) 用來發(fā)起請求
BeautifulSoup(bs4) 用來解析HTML結(jié)構(gòu)并提取內(nèi)容
faker(http://fake-factory.readthedocs.io/en/stable/)用來模擬請求UA(User-Agent)

主要思路是分成兩部分,第一部分用來發(fā)起請求分析出播放列表然后丟到隊列中,第二部分在隊列中逐條下載文件到本地,一般分析列表速度更快,下載速度比較慢可以借助多線程同時進行下載。
主要代碼如下:

#-*- coding: utf-8 -*-
'''by sudo rm -rf  http://imchenkun.com'''
import os
import requests
from bs4 import BeautifulSoup
import random
from faker import Factory
import Queue
import threading

fake = Factory.create()
luoo_site = 'http://www.luoo.net/music/'
luoo_site_mp3 = 'http://luoo-mp3.kssws.ks-cdn.com/low/luoo/radio%s/%s.mp3'

proxy_ips = [    '27.15.236.236'    ] # 替換自己的代理IP
headers = {
    'Connection': 'keep-alive',
    'User-Agent': fake.user_agent()
    }

def random_proxies():
    ip_index = random.randint(0, len(proxy_ips)-1)
    res = { 'http': proxy_ips[ip_index] }
    return res

def fix_characters(s):
    for c in ['<', '>', ':', '"', '/', '\\\\', '|', '?', '*']:
        s = s.replace(c, '')
    return s


class LuooSpider(threading.Thread):
    def __init__(self, url, vols, queue=None):
        threading.Thread.__init__(self)
        print '[luoo spider]'
        print '=' * 20
        self.url = url
        self.queue = queue
        self.vol = '1'
        self.vols = vols

    def run(self):
        for vol in self.vols:
            self.spider(vol)
        print '\\ncrawl end\\n\\n'
        def spider(self, vol):
        url = luoo_site + vol
        print 'crawling: ' + url + '\\n'
        res = requests.get(url, proxies=random_proxies())
                soup = BeautifulSoup(res.content, 'html.parser')
        title = soup.find('span', attrs={'class': 'vol-title'}).text
        cover = soup.find('img', attrs={'class': 'vol-cover'})['src']
        desc = soup.find('div', attrs={'class': 'vol-desc'})
        track_names = soup.find_all('a', attrs={'class': 'trackname'})
        track_count = len(track_names)
        tracks = []
        for track in track_names:
            _id = str(int(track.text[:2])) if (int(vol) < 12) else track.text[:2]  # 12期前的音樂編號1~9是1位(如:1~9),之后的都是2位 1~9會在左邊墊0(如:01~09)
            _name = fix_characters(track.text[4:])
            tracks.append({'id': _id, 'name': _name})
            phases = {
                'phase': vol,                         # 期刊編號
                'title': title,                       # 期刊標(biāo)題
                 'cover': cover,                      # 期刊封面
                 'desc': desc,                        # 期刊描述
                 'track_count': track_count,          # 節(jié)目數(shù)
                 'tracks': tracks                     # 節(jié)目清單(節(jié)目編號,節(jié)目名稱)
            }
            self.queue.put(phases)


class LuooDownloader(threading.Thread):
    def __init__(self, url, dist, queue=None):
        threading.Thread.__init__(self)
        self.url = url
        self.queue = queue
        self.dist = dist
        self.__counter = 0       

     def run(self):
        while True:
            if self.queue.qsize() <= 0:
                pass
            else:
                phases = self.queue.get()
                self.download(phases)

    def download(self, phases):
        for track in phases['tracks']:
            file_url = self.url % (phases['phase'], track['id'])

            local_file_dict = '%s/%s' % (self.dist, phases['phase'])
            if not os.path.exists(local_file_dict):
                os.makedirs(local_file_dict)              

            local_file = '%s/%s.%s.mp3' % (local_file_dict, track['id'], track['name'])
            if not os.path.isfile(local_file):
                print 'downloading: ' + track['name']
                res = requests.get(file_url, proxies=random_proxies(), headers=headers)
                with open(local_file, 'wb') as f:
                    f.write(res.content)
                    f.close()
                print 'done.\\n'
            else:
                print 'break: ' + track['name']


if __name__ == '__main__':
    spider_queue = Queue.Queue()

    luoo = LuooSpider(luoo_site, vols=['680', '721', '725', '720'],queue=spider_queue)
    luoo.setDaemon(True)
    luoo.start()

    downloader_count = 5
    for i in range(downloader_count):
        luoo_download = LuooDownloader(luoo_site_mp3, 'D:/luoo', queue=spider_queue)
        luoo_download.setDaemon(True)
        luoo_download.start()

以上代碼執(zhí)行后結(jié)果如下圖所示



Github地址

總結(jié)


通過本文我們基本了解了網(wǎng)絡(luò)爬蟲的知識,對網(wǎng)絡(luò)爬蟲工作原理認(rèn)識的同時我們實現(xiàn)了一個真實的案例場景,這里主要是使用一些基礎(chǔ)的第三方Python庫來幫助我們實現(xiàn)爬蟲,基本上演示了網(wǎng)絡(luò)爬蟲框架中基本的核心概念。通常工作中我們會使用一些比較優(yōu)秀的爬蟲框架來快速的實現(xiàn)需求,比如 scrapy框架,接下來我會通過使用Scrapy這類爬蟲框架來實現(xiàn)一個新的爬蟲來加深對網(wǎng)絡(luò)爬蟲的理解!

特別申明:本文所提到的落網(wǎng)是我本人特別喜歡的一個音樂網(wǎng)站,本文只是拿來進行爬蟲的技術(shù)交流學(xué)習(xí),讀者涉及到的所有侵權(quán)問題都與本人無關(guān)

本文首發(fā)在sudo rm -rf 轉(zhuǎn)載請注明原作者

--EOF--

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,517評論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,087評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,521評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,493評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,207評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,603評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,624評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,813評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,364評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,110評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,305評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,874評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,532評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,953評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,209評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,033評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,268評論 2 375

推薦閱讀更多精彩內(nèi)容