(2018-05-18.Python從Zero到One)2嘉涌、(爬蟲)非結(jié)構(gòu)化數(shù)據(jù)與結(jié)構(gòu)化數(shù)據(jù)提取__1.2.2案例:使用正則表達式的爬蟲

案例:使用正則表達式的爬蟲

現(xiàn)在擁有了正則表達式這把神兵利器,我們就可以進行對爬取到的全部網(wǎng)頁源代碼進行篩選了浪慌。

下面我們一起嘗試一下爬取內(nèi)涵段子網(wǎng)站: http://www.neihan8.com/article/list_5_1.html

打開之后,不難看到里面一個一個灰常有內(nèi)涵的段子朴则,當(dāng)你進行翻頁的時候权纤,注意url地址的變化:

這樣我們的url規(guī)律找到了,要想爬取所有的段子,只需要修改一個參數(shù)即可汹想。 下面我們就開始一步一步將所有的段子爬取下來吧外邓。


第一步:獲取數(shù)據(jù)

1. 按照我們之前的用法,我們需要寫一個加載頁面的方法欧宜。

這里我們統(tǒng)一定義一個類坐榆,將url請求作為一個成員方法處理。

我們創(chuàng)建一個文件冗茸,叫duanzi_spider.py

然后定義一個Spider類,并且添加一個加載頁面的成員方法

import urllib2

class Spider:
    """
        內(nèi)涵段子爬蟲類
    """
    def loadPage(self, page):
        """
            @brief 定義一個url請求網(wǎng)頁的方法
            @param page 需要請求的第幾頁
            @returns 返回的頁面html
        """

    url = "http://www.neihan8.com/article/list_5_" + str(page)
+ ".html"
    #User-Agent頭
    user_agent = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT
6.1; Trident/5.0'

    headers = {'User-Agent': user_agent}
    req = urllib2.Request(url, headers = headers)
    response = urllib2.urlopen(req)
    html = response.read()
    print html

    #return html

以上的loadPage的實現(xiàn)體想必大家應(yīng)該很熟悉了匹中,需要注意定義python類的成員方法需要額外添加一個參數(shù)self.

  • 那么loadPage(self, page) 中的page是我們指定去請求第幾頁夏漱。

  • 最后通過 print html打印到屏幕上。

  • 然后我們寫一個main函數(shù)見到測試一個loadPage方法

2. 寫main函數(shù)測試一個loadPage方法
if __name__ == '__main__':
    """
        ======================
            內(nèi)涵段子小爬蟲
        ======================
    """
    print '請按下回車開始'
    raw_input()

    #定義一個Spider對象
    mySpider = Spider()
    mySpider.loadpage(1)

  • 程序正常執(zhí)行的話顶捷,我們會在屏幕上打印了內(nèi)涵段子第一頁的全部html代碼挂绰。 但是我們發(fā)現(xiàn),html中的中文部分顯示的可能是亂碼 服赎。
day52_爬蟲-非結(jié)構(gòu)化數(shù)據(jù)與結(jié)構(gòu)化數(shù)據(jù)提取-01.png

那么我們需要簡單的將得到的網(wǎng)頁源代碼處理一下:


def loadPage(self, page):
    """
        @brief 定義一個url請求網(wǎng)頁的方法
        @param page 需要請求的第幾頁
        @returns 返回的頁面html
    """

    url = "http://www.neihan8.com/article/list_5_" + str(page)
+ ".html"
    #User-Agent頭
    user_agent = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT
6.1; Trident/5.0'
    headers = {'User-Agent': user_agent}
    req = urllib2.Request(url, headers = headers)
    response = urllib2.urlopen(req)
    html = response.read()
    gbk_html = html.decode('gbk').encode('utf-8')
    # print gbk_html
    return gbk_html

注意 :對于每個網(wǎng)站對中文的編碼各自不同葵蒂,所以html.decode(‘gbk’)的寫法并不是通用寫法,根據(jù)網(wǎng)站的編碼而異

  • 這樣我們再次執(zhí)行以下duanzi_spider.py 重虑,會發(fā)現(xiàn)之前的中文亂碼可以正常顯示了践付。
day52_爬蟲-非結(jié)構(gòu)化數(shù)據(jù)與結(jié)構(gòu)化數(shù)據(jù)提取-02.png

第二步:篩選數(shù)據(jù)

接下來我們已經(jīng)得到了整個頁面的數(shù)據(jù)。 但是缺厉,很多內(nèi)容我們并不關(guān)心永高,所以下一步我們需要進行篩選。 如何篩選提针,就用到了上一節(jié)講述的正則表達式命爬。

  • 首先
import re

  • 然后, 在我們得到的gbk_html中進行篩選匹配。

我們需要一個匹配規(guī)則:

我們可以打開內(nèi)涵段子的網(wǎng)頁辐脖,鼠標點擊右鍵 “ 查看源代碼 ” 你會驚奇的發(fā)現(xiàn)饲宛,我們需要的每個段子的內(nèi)容都是在一個 <div>標簽中,而且每個div都有一個屬性class = "f18 mb20"

day52_爬蟲-非結(jié)構(gòu)化數(shù)據(jù)與結(jié)構(gòu)化數(shù)據(jù)提取-03.png

所以嗜价,我們只需要匹配到網(wǎng)頁中所有<div class="f18 mb20"></div> 的數(shù)據(jù)就可以了艇抠。

根據(jù)正則表達式,我們可以推算出一個公式是:
<div.*?class="f18 mb20">(.*?)</div>
  • 這個表達式實際上就是匹配到所有divclass="f18 mb20 里面的內(nèi)容(具體可以看前面正則介紹)

  • 然后將這個正則應(yīng)用到代碼中炭剪,我們會得到以下代碼:

def loadPage(self, page):
    """
        @brief 定義一個url請求網(wǎng)頁的方法
        @param page 需要請求的第幾頁
        @returns 返回的頁面html
    """

    url = "http://www.neihan8.com/article/list_5_" + str(page)
+ ".html"
    #User-Agent頭
    user_agent = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT
6.1; Trident/5.0'
    headers = {'User-Agent': user_agent}
    req = urllib2.Request(url, headers = headers)
    response = urllib2.urlopen(req)
    html = response.read()
    gbk_html = html.decode('gbk').encode('utf-8')

    #找到所有的段子內(nèi)容<div class = "f18 mb20"></div>
    #re.S 如果沒有re.S 則是只匹配一行有沒有符合規(guī)則的字符串练链,如果沒有則下一行重新匹配
    # 如果加上re.S 則是將所有的字符串將一個整體進行匹配
    pattern = re.compile(r'<div.*?class="f18 mb20">(.*?)</di
v>', re.S)
    item_list = pattern.findall(gbk_html)

    return item_list

def printOnePage(self, item_list, page):
    """
        @brief 處理得到的段子列表
        @param item_list 得到的段子列表
        @param page 處理第幾頁
    """

    print "******* 第 %d 頁 爬取完畢...*******" %page
    for item in item_list:
        print "================"
        print ite

  • 這里需要注意一個是re.S是正則表達式中匹配的一個參數(shù)。
  • 如果 沒有re.S 則是 只匹配一行 有沒有符合規(guī)則的字符串奴拦,如果沒有則下一行重新匹配媒鼓。
  • 如果 加上re.S 則是將 所有的字符串 將一個整體進行匹配,findall 將所有匹配到的結(jié)果封裝到一個list中。
  • 然后我們寫了一個遍歷item_list的一個方法 printOnePage() 绿鸣。 ok程序?qū)懙竭@疚沐,我們再一次執(zhí)行一下潮模。
Power@PowerMac ~$ python duanzi_spider.py

我們第一頁的全部段子,不包含其他信息全部的打印了出來。
  • 你會發(fā)現(xiàn)段子中有很多 <p> , </p> 很是不舒服,實際上這個是html的一種段落的標簽。

  • 在瀏覽器上看不出來别智,但是如果按照文本打印會有<p>出現(xiàn),那么我們只需要把我們不希望的內(nèi)容去掉即可了。

  • 我們可以如下簡單修改一下 printOnePage().

def printOnePage(self, item_list, page):
    """
        @brief 處理得到的段子列表
        @param item_list 得到的段子列表
        @param page 處理第幾頁
    """

    print "******* 第 %d 頁 爬取完畢...*******" %page
    for item in item_list:
        print "================"
        item = item.replace("<p>", "").replace("</p>", "").repl
ace("<br />", "")
        print item


第三步:保存數(shù)據(jù)

  • 我們可以將所有的段子存放在文件中倚评。比如,我們可以將得到的每個item不是打印出來蛹尝,而是存放在一個叫 duanzi.txt 的文件中也可以构眯。
def writeToFile(self, text):
'''
    @brief 將數(shù)據(jù)追加寫進文件中
    @param text 文件內(nèi)容
'''
    myFile = open("./duanzi.txt", 'a') #追加形式打開文件
    myFile.write(text)
    myFile.write("---------------------------------------------
--------")
    myFile.close()

  • 然后我們將print的語句 改成writeToFile() 壹店,當(dāng)前頁面的所有段子就存在了本地的MyStory.txt文件中。
def printOnePage(self, item_list, page):
'''
    @brief 處理得到的段子列表
    @param item_list 得到的段子列表
    @param page 處理第幾頁
'''
    print "******* 第 %d 頁 爬取完畢...*******" %page
    for item in item_list:
        # print "================"
        item = item.replace("<p>", "").replace("</p>", "").repl
ace("<br />", "")
        # print item
        self.writeToFile(item)

第四步:顯示數(shù)據(jù)

  • 接下來我們就通過參數(shù)的傳遞對page進行疊加來遍歷 內(nèi)涵段子吧的全部段子內(nèi)容抬旺。

  • 只需要在外層加一些邏輯處理即可祥楣。

def doWork(self):
'''
    讓爬蟲開始工作
'''
    while self.enable:
        try:
            item_list = self.loadPage(self.page)
        except urllib2.URLError, e:
            print e.reason
            continue

        #對得到的段子item_list處理
        self.printOnePage(item_list, self.page)
        self.page += 1 #此頁處理完畢开财,處理下一頁
        print "按回車繼續(xù)..."
        print "輸入 quit 退出"
        command = raw_input()
        if (command == "quit"):
            self.enable = False
            break

  • 最后,我們執(zhí)行我們的代碼误褪,完成后查看當(dāng)前路徑下的duanzi.txt文件责鳍,里面已經(jīng)有了我們要的內(nèi)涵段子。

以上便是一個非常精簡使用的小爬蟲程序兽间,使用起來很是方便历葛,如果想要爬取其他網(wǎng)站的信息,只需要修改其中某些參數(shù)和一些細節(jié)就行了嘀略。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末恤溶,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子帜羊,更是在濱河造成了極大的恐慌咒程,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件讼育,死亡現(xiàn)場離奇詭異帐姻,居然都是意外死亡阐斜,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門钞馁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坪稽,“玉大人,你說我怎么就攤上這事扛伍】昶瑁” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵刺洒,是天一觀的道長鳖宾。 經(jīng)常有香客問我,道長逆航,這世上最難降的妖魔是什么鼎文? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮因俐,結(jié)果婚禮上拇惋,老公的妹妹穿的比我還像新娘。我一直安慰自己抹剩,他們只是感情好撑帖,可當(dāng)我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著澳眷,像睡著了一般胡嘿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上钳踊,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天衷敌,我揣著相機與錄音,去河邊找鬼拓瞪。 笑死缴罗,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的吴藻。 我是一名探鬼主播瞒爬,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼沟堡!你這毒婦竟也來了侧但?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤航罗,失蹤者是張志新(化名)和其女友劉穎禀横,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體粥血,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡柏锄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年酿箭,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片趾娃。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡缭嫡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出抬闷,到底是詐尸還是另有隱情妇蛀,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布笤成,位于F島的核電站评架,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏炕泳。R本人自食惡果不足惜纵诞,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望培遵。 院中可真熱鬧浙芙,春花似錦、人聲如沸籽腕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽节仿。三九已至,卻和暖如春掉蔬,著一層夾襖步出監(jiān)牢的瞬間廊宪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工女轿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留箭启,地道東北人。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓蛉迹,卻偏偏與公主長得像傅寡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子北救,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,527評論 2 349

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