Python爬蟲實例:糗百

看了下python爬蟲用法,正則匹配過濾對應字段,這裏進行最強外功:copy大法實踐html

一開始是直接從參考連接複製粘貼的,發現因爲糗百改版致使失敗,這裏對新版html分析後進行了簡單改進,把整理過程記錄以下:python

參考文章中是這樣的:正則表達式

截圖參考中的html文件佈局以下:app

分析參考中的僞代碼以下:python爬蟲

分析圖中html佈局僞代碼:ide

<div>
    <div class=‘author’>
        <a>
            <img></img>
            「暱稱」
        </a>
    </div>
    <div class=‘content’>
        「內容」
    </div>
    <div class=‘status’>
        <span></span>
        <span></span>
        <span></span>
    </div>
</div>

進行匹配的正則表達式爲:佈局

'<div.*?author">.*?<a.*?<img.*?>(.*?)</a>.*?<div.*?' +
                     'content">(.*?)<!--(.*?)-->.*?</div>(.*?)<div class="stats.*?class="number">(.*?)</i>'

根據正則進行篩選過濾的python代碼爲:(python代碼每次執行都一致,不一樣的事正則表達式,執行代碼中的正則表達式替換爲文字,複製上下文中的進行替換便可)學習

# -*- coding: UTF-8 -*-

import urllib
import urllib2
import re

def qiubaiWithoutImageTest():
    page = 1
    url = 'http://www.qiushibaike.com/hot/page/' + str(page)
    user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
    headers = {'User-Agent': user_agent}
    try:
        request = urllib2.Request(url, headers=headers)
        response = urllib2.urlopen(request)
        content = response.read().decode('utf-8')
        # pattern = re.compile('<div.*?author">.*?<a.*?<img.*?>(.*?)</a>.*?<div.*?' +
        #                      'content">(.*?)<!--(.*?)-->.*?</div>(.*?)<div class="stats.*?class="number">(.*?)</i>',
        #                      re.S)
        pattern = re.compile('正則表達式',
                             re.S)
        items = re.findall(pattern, content)
        print items
        for item in items:
            print item[0],item[1],item[2],item[3]
            # haveImg = re.search("img", item[3])
            # if not haveImg:
            #     # print item
            #     print item[0], item[1], item[2], item[4]
    except urllib2.URLError, e:
        if hasattr(e, "code"):
            print e.code
        if hasattr(e, "reason"):
            print e.reason

#執行代碼
qiubaiWithoutImageTest()

可是,據說可是以前的話都是廢話。。。ui

可是由於糗百改版成以下圖中的格式:編碼

因此只能參考照貓畫虎按照新格式進行正則表達式的修改了:

分析新的html僞代碼格式以下:

<div>
    <div class=‘author’>
        <a><img></img></a>
        <a><h2>’暱稱’</h2></a>
        <div>年齡</div>
    </div>
    <a class=‘contentHerf’>
        <div class=‘content’>
            <span>’內容’</span>
        </div>
    </a>
    <div class=‘status’>
        <span></span>
        <span></span>
        <span></span>
    </div>
</div>

因此新版的正則表達式修改以下:

LZ正則水平有限,進行了屢次嘗試才匹配成功。。。,把各個版本記錄以下
=======版本1(未經過)
'<div.*?author">.*?<a.*?<img.*?>(.*?)</a>.*?<a.*?><h2.*?>(.*?)</h2>.*?</a>.*?<a.*?contentHerf">.*?<div.*?' +
                     'content」>(.*?)<span.*?>(.*?)</span>.*?<!--(.*?)-->.*?</div>(.*?)</a>.*?<div class="stats.*?class="number">(.*?)</i>'

========版本2(未經過)
'<div.*?author">.*?<a.*?<img.*?>(.*?)</a>.*?<a.*?><h2.*?>(.*?)</h2>.*?</a>.*?<a.*?contentHerf">.*?<div.*?content">(.*?)<span.*?>(.*?)</span>.*?<!--(.*?)-->.*?</div>(.*?)</a>.*?<div class="stats.*?class="number">(.*?)</i>'

=========版本3(未經過)
'<div.*?author">.*?<a.*?<img.*?>(.*?)</a>.*?<a.*?>.*?<h2.*?>(.*?)</h2>.*?</a>.*?<a.*?contentHerf">.*?<div.*?content">(.*?)<span.*?>(.*?)</span>.*?</div>.*?</a>.*?<div class="stats.*?class="number">(.*?)</i>'


=========版本4(經過僅有內容)
'<div.*?content">(.*?)<span.*?>(.*?)</span>.*?</div>'

=========版本5(經過:內容、暱稱)
'<div.*?author clearfix">.*?<a.*?<img.*?>(.*?)</a>.*?<a.*?<h2.*?>(.*?)</h2>.*?</a>.*?</div>.*?<div.*?content">(.*?)<span.*?>(.*?)</span>.*?</div>'

=========版本6(經過:內容、暱稱、年齡)
'<div.*?author clearfix">.*?<a.*?<h2.*?>(.*?)</h2>.*?</a>.*?<div.*?articleGender manIcon">(.*?)</div>.*?</div>.*?<div.*?content">(.*?)<span.*?>(.*?)</span>.*?</div>'

最終終於看到了以下結果:

胖香嬌喘助理
31 
老妹單身好久了,一直沒對象,那天跟我出去坐公交,身邊站着一個小夥子,小婊砸一直往人小夥子身邊蹭。<br/>忽然,這小婊砸捂着頭:「哎呦!我頭暈,不行,暈了。。。」說着,順勢倒在人家小夥子懷裏。<br/>小夥子嚇壞了,搖了搖老妹:「大姐,大姐,您沒事吧!」<br/>老妹一聽,怒不可遏:「叫誰大姐呢?我有這麼老嗎?」說着,給了人家一個白眼,還沒到站就下車了。<br/>剩我一臉矇蔽。。這招幾百年前就有人用了。

萌面大叔l
26 
我對蟬說,他日再見要等來年!蟬對我說,他日重逢要等來生!

逍遙ベ假行僧
29 
初聞不知曲中意,在聽已經是曲中人。                                  現知詞意惟落淚,不見當年陪孤人。                               既然亦是曲中人,爲什麼還聽曲中曲。                              曲中思念今猶在,不見當年夢中人。

逆流而上669
26 
一次歷史考試,問:1966年至1999年發生了哪三件大事。一奇葩同窗是這樣回答的:「1969年,我爸出生了;1972年我媽出生了;1995年,一個晴天霹靂,神通常的人物——我誕生了!」而後這張試卷就在公告欄裏掛了一個星期!


匿名用戶 38 
公司高層來咱們基層調研,到咱們單位的是位副總,筆桿子小李又開始嘚瑟着發報道,還把稿子發到咱們單位羣,其中有這幾句話「某總深刻基層調研一線生產生活狀況,與一線職工同吃同住......」我@了他一下,說:「在職工前面加個女字就更好了。」就在這時,某副總@了我一下:「到我辦公室來一下。」我擦,誰把副總拉羣裏來的?[哀怨][哀怨][哀怨]

匿名用戶 0 
沒有更好的辦法了

a金釗
24 
男生用「沒事,不疼。」欺騙了多少女生;女生用「啊,疼!」欺騙了多少男生。

青青子衿憂我心
24 
甲:怎麼了?看着你氣色不太好<br/>乙:昨兒喝多了,也吐也瀉<br/><br/>甲:喝多少啊?成這德行<br/>乙:喝了一打老酸奶。。。<br/>聽得都TM醉了,,,,

請叫我小智
21 
看懂絕逼是污神。

surepman
22 
這真不是故意的

傻晴°
38 
開會,女同事讓我坐她旁邊,我心裏一陣激動。我坐定後,她拿出手機玩了起來,說:你坐這領導(在側面)就看不見我了。

挖鼻孔的老虎
99 
晚上回到家,老婆用手機邊拍我邊問:「不是說加班嗎,怎麼有酒味?」<br/>我面對攝像頭有點不自在:「我,我口渴,路上買了瓶啤酒喝。」<br/>老婆拿着手機搗鼓了好一下子,而後說:「我媽不信、我妹妹不信、我全體閨蜜不信,連我9歲的侄女都以爲你沒加班只是去了喝酒。」

今狐小妖
30 
二樓二樓,別拿着手機看了電話不會打來的

你的選擇你的選擇
35 
這一家子拖鞋真會放,整齊,還有什麼?

LZ是Python新手,水平有限,僅做爲學習參考使用!

貼上後續參考中的進階代碼

# -*- coding: UTF-8 -*-

import urllib
import urllib2
import re
import thread
import time

# 糗事百科爬蟲類
class QSBK:
    # 初始化方法,定義一些變量
    def __init__(self):
        self.pageIndex = 1
        self.user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
        # 初始化headers
        self.headers = {'User-Agent': self.user_agent}
        # 存放段子的變量,每個元素是每一頁的段子們
        self.stories = []
        # 存放程序是否繼續運行的變量
        self.enable = False

    # 傳入某一頁的索引得到頁面代碼
    def getPage(self, pageIndex):
        try:
            url = 'http://www.qiushibaike.com/hot/page/' + str(pageIndex)
            # 構建請求的request
            request = urllib2.Request(url, headers=self.headers)
            # 利用urlopen獲取頁面代碼
            response = urllib2.urlopen(request)
            # 將頁面轉化爲UTF-8編碼
            pageCode = response.read().decode('utf-8')
            # print pageCode
            return pageCode

        except urllib2.URLError, e:
            if hasattr(e, "reason"):
                print u"鏈接糗事百科失敗,錯誤緣由", e.reason
                return None

    # 傳入某一頁代碼,返回本頁不帶圖片的段子列表
    def getPageItems(self, pageIndex):
        pageCode = self.getPage(pageIndex)
        if not pageCode:
            print "頁面加載失敗...."
            return None
        pattern = re.compile('<div.*?author clearfix">.*?<a.*?<h2.*?>(.*?)</h2>.*?</a>.*?<div.*?articleGender manIcon">(.*?)</div>.*?</div>.*?<div.*?content">(.*?)<span.*?>(.*?)</span>.*?</div>',
                             re.S)
        items = re.findall(pattern, pageCode)
        # 用來存儲每頁的段子們
        pageStories = []
        # 遍歷正則表達式匹配的信息
        for item in items:

            for itemInItem in item:
                pageStories.append(itemInItem.strip())
                print itemInItem

            # 是否含有圖片
            # haveImg = re.search("img", item[3])
            # # 若是不含有圖片,把它加入list中
            # if not haveImg:
            #     replaceBR = re.compile('<br/>')
            #     text = re.sub(replaceBR, "\n", item[1])
            #     # item[0]是一個段子的發佈者,item[1]是內容,item[2]是發佈時間,item[4]是點贊數
            #     pageStories.append([item[0].strip(), text.strip(), item[2].strip(), item[4].strip()])
        return pageStories

    # 加載並提取頁面的內容,加入到列表中
    def loadPage(self):
        # 若是當前未看的頁數少於2頁,則加載新一頁
        if self.enable == True:
            if len(self.stories) < 2:
                # 獲取新一頁
                pageStories = self.getPageItems(self.pageIndex)
                # 將該頁的段子存放到全局list中
                if pageStories:
                    self.stories.append(pageStories)
                    # 獲取完以後頁碼索引加一,表示下次讀取下一頁
                    self.pageIndex += 1

    # 調用該方法,每次敲回車打印輸出一個段子
    def getOneStory(self, pageStories, page):
        # 遍歷一頁的段子
        for story in pageStories:
            # 等待用戶輸入
            input = raw_input()
            # 每當輸入回車一次,判斷一下是否要加載新頁面
            self.loadPage()
            # 若是輸入Q則程序結束
            if input == "Q":
                self.enable = False
                return
            print u"第%d頁\t發佈人:%s\t發佈時間:%s\t贊:%s\n%s" % (page, story[0], story[2], story[3], story[1])

    # 開始方法
    def start(self):
        print u"正在讀取糗事百科,按回車查看新段子,Q退出"
        # 使變量爲True,程序能夠正常運行
        self.enable = True
        # 先加載一頁內容
        self.loadPage()
        # 局部變量,控制當前讀到了第幾頁
        nowPage = 0
        while self.enable:
            if len(self.stories) > 0:
                # 從全局list中獲取一頁的段子
                pageStories = self.stories[0]
                # 當前讀到的頁數加一
                nowPage += 1
                # 將全局list中第一個元素刪除,由於已經取出
                del self.stories[0]
                # 輸出該頁的段子
                self.getOneStory(pageStories, nowPage)

qbspider = QSBK()
qbspider.start()#在log中敲入enter進行下一頁數據展現,目前還有一些問題

 

參考連接:

Python爬蟲入門七之正則表達式

Python爬蟲實戰一之爬取糗事百科段子

python學習筆記三:解析html(HTMLParser、SGMLParser),並抓取圖片

小練習 SGMLParser 解析 HTML

使用python 提取html文件中的特定數據

Beautiful Soup 4.2.0 文檔

python:BeautifulSoup 模塊使用指南

相關文章
相關標籤/搜索