聚沙成塔--爬蟲系列(七)(妹子,快到碗里來)

版權(quán)聲明:本文為作者原創(chuàng)文章,可以隨意轉(zhuǎn)載,但必須在明確位置標(biāo)明出處?。?!

前面章節(jié)的代碼可以看出,我們并沒有把「好笑數(shù)」,「圖像的url地址」取到,從糗百主頁我們可以看到有些用戶發(fā)表的段子里包含了圖片,那我們怎么取到這些圖片呢,本篇老謝將教會大家如何把網(wǎng)絡(luò)上的圖片取到本地,這個技能你們一定要get到。get到了以后再看到漂亮妹子的圖片再也不用右鍵將圖片保存在本地了,哈哈哈...;此種神功,我練定了。

東方不敗-林青霞

練此神功口訣

通過糗事百科主頁我們可以看出有些用戶發(fā)表的段子帶了圖片,有些又沒有圖片只有文本內(nèi)容,前面文章的代碼我們只能取出每個用戶的文本內(nèi)容并不能取到圖片內(nèi)容,那么要怎么才能取到圖片內(nèi)容呢?

  • 口訣一:觀察!觀察!觀察!
    重要的事說三遍,做爬蟲最精髓的地方就是觀察,外加一點(diǎn)猜測,觀察什么呢,觀察帶圖片發(fā)表的用戶和只有文本用戶在html源碼中的區(qū)別,怎么在源碼中快速找到它們的區(qū)別呢,當(dāng)然是用F12開發(fā)者工具了,如果你是初學(xué)者請一定要看前面章節(jié)的內(nèi)容。
  • 口訣二: 過濾,篩選
    觀察過后,使用正則表達(dá)式過濾,篩選是個永恒的主題,當(dāng)然后面我們還會講到Beautify soup、xpath、lxml等第三方庫,第三方庫有它的優(yōu)勢,也有它的劣勢,就拿Beautify Soup來說,如果我們訪問的頁面不標(biāo)準(zhǔn)或者不完整,那么你或許拿不到你想要的結(jié)果。這種第三方庫解決不了的問題就只能用最原始的正則表達(dá)式了,所以學(xué)好正則表達(dá)式是你不得不具備的技能。

觀察

通過F12開發(fā)者工具我們看看帶圖片的和不帶圖片的有什么區(qū)別,當(dāng)我們通過快速定位是可以看到有圖片的包含在一個</div class='thumb'>...</div>中,這個時候我們不要馬上就取編寫正則表達(dá)式,我們還得去看看沒有圖片的有沒有包含這對元素,如果有那么我們編寫代碼的邏輯就會和沒有的不一樣了,通過觀察我們發(fā)現(xiàn)不帶圖片的并沒有包含</div class='thumb'>...</div>這對元素,如下圖:

帶圖片和不帶圖片的差異

過濾

差異找到了剩下的就是過濾了,如何過濾呢,這里就需要我們稍稍東東腦子了,想想有的用戶發(fā)表是帶了圖片的有的用戶發(fā)表是沒有帶圖片的,如果這個時候我們還像前面文章那樣把正則表達(dá)式寫在

pattern = re.compile(r'<a href="(.*?)".*?<h2>(.*?)</h2>.*?<div class="content">(.*?)</div>.*?<div class="thumb">.*?src="(.*?)".*?<i class="number">(.*?)</i>', re.S)

這個表達(dá)式里,那么我們肯定得不到我們想要的結(jié)果,想想是為什么,因為如果某個用戶沒有發(fā)表圖片,那么我們使用這個表達(dá)式肯定連該用戶發(fā)表的文本信息也拿不到了。所以我們必須的把匹配圖片的正則表達(dá)式和之前的正則表達(dá)式分開來寫

pattern = re.compile(r'<a href="(.*?)".*?<h2>(.*?)</h2>.*?<div class="content">(.*?)</div>.*?<i class="number">(.*?)</i>', re.S)
picture = re.compile(r'<div class="thumb">.*?src="(.*?)"', re.S)

編碼實現(xiàn)

from urllib import request
from urllib import error
import re
import os
url = 'https://www.qiushibaike.com'
user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'
headers = {'User-Agent': user_agent}


def read_html(url, headers, codec):
    '''[read_html]
    [讀取html頁面內(nèi)容]
    Arguments:
        url {[string]} -- [url地址]
        headers {[dict]} -- [用戶代理,這里是一個字典類型]
        codec {[string]} -- [編碼方式]    
    Returns:
        [string] -- [頁面內(nèi)容]
    '''
    # 構(gòu)建一個請求對象
    try:
        req = request.Request(url, headers=headers)
        # 打開一個請求
        response = request.urlopen(req)
        # 讀取服務(wù)器返回的頁面數(shù)據(jù)內(nèi)容
        content = response.read().decode(codec)
        return content
    except error.URLError as e:
        print(e.reason)
        return None
def match_element(content, pattern):
    '''[match_element]
    
    [匹配元素]
    
    Arguments:
        content {[string]} -- [文本內(nèi)容]
        pattern {[object]} -- [匹配模式]

    Returns:
        [list] -- [匹配到的元素]
    '''
    # 匹配所有用戶信息
    
    userinfos = re.findall(pattern, content)
    
    return userinfos

content = read_html(url, headers, 'utf-8')
pattern = re.compile(r'<div class="article block untagged mb15[\s\S]*?class="stats-vote".*?</div>', re.S)
if content:
    userinfos = match_element(content, pattern)

    if userinfos:
        pattern = re.compile(r'<a href="(.*?)".*?<h2>(.*?)</h2>.*?<div class="content">(.*?)</div>.*?<i class="number">(.*?)</i>', re.S)
        picture = re.compile(r'<div class="thumb">.*?src="(.*?)"', re.S)
        for userinfo in userinfos:
            item = match_element(userinfo, pattern)
            pictures = match_element(userinfo, picture)
            try:
                if item:
                    userid, name, content, num = item[0]
                    # 去掉換行符,<span></span>,<br/>符號
                    userid = re.sub(r'\n|<span>|</span>|<br/>', '', userid)
                    name = re.sub(r'\n|<span>|</span>|<br/>', '', name)
                    content = re.sub(r'\n|<span>|</span>|<br/>', '', content)
                    
                    if pictures:
                        path = './users/'
                        if not os.path.exists(path):
                            os.makedirs(path)

                        request.urlretrieve('http:' + pictures[0], path + os.path.basename(pictures[0]))
                    
                        print((userid, name, content, num, pictures[0]))
                    else:
                        print((userid, name, content, num ))
            except Exception as e:
                print(e)

執(zhí)行結(jié)果

('/users/20735073/', '優(yōu)雅文藝范', '我小徒弟問我:“師傅,你多大了?”“22啊,問這個干嘛”“那你結(jié)婚了嗎”“沒有啊”“你怎么還不結(jié)婚???現(xiàn)在像你這么大的二胎都會走路了”“那你多大了?”“22啊”“那你孩子呢?”“在家我婆婆帶著呢,怎么了?”“。。。沒事,我就問問”', '683')
('/users/30716689/', '蒼老師首席女配音', '閨蜜懷孕中,抱怨老公回家就躲在客廳打游戲,經(jīng)常鬧別扭。一次偶然的機(jī)會,她遇到大師,大師說她家風(fēng)水有問題,要改變房間格局。閨蜜聽大師的安排,果然,老公回家就往臥室鉆,不玩手機(jī)也不吵鬧了。我好奇的問閨蜜,大師真那么靈驗,你怎么改房間格局的?閨蜜笑笑,也沒有什么,只是把客廳的路由器改在臥室窗臺。', '988')
('/users/33065062/', '耶穌安拉寧有種乎', '初中時候,班里有個很漂亮女孩,屬于班花那種,有次下課我往她臉上親了一口就跑,其實我一點(diǎn)都不喜歡她,她男友是學(xué)校外面那種小混混,我就喜歡那種被追著打一個星期的感覺,死亡如風(fēng),常伴吾身。', '411')
('/users/28491276/', '不知取什么名903…', '組織淫才給我答案', '227', '//pic.qiushibaike.com/system/pictures/11966/119663321/medium/app119663321.jpg')
('/users/26635010/', '本少丶霸道', '這個OK么', '15', '//pic.qiushibaike.com/system/pictures/10590/105905488/medium/app105905488.jpg')
('/users/10144082/', '°小姐姐', '閨蜜看上了一支TF(湯姆福特)的口紅,我們倆正在討論,老公湊過來問:聊什么呢?我:口紅,說了你也不懂。老公看到我手機(jī)上的圖片激動的說:這個我知道我知道。TFboys,他們還賣口紅啊。-_-||。。。。。', '1653')
('/users/5623502/', '"別扭丶!', '最近幾天把衣柜翻了個底朝天都沒找到我想穿的那件秋衣,問老公吧,逗逗他?!拔夷乔镆挛以趺匆舱也坏搅耍闶遣皇峭低到o誰了?”“你還找我要?還我給誰?你不定丟誰家了呢?”我擦,好想問候他祖宗十八代!', '4460')
('/users/30031169/', '空霖', '今天中午做了個終生難忘的夢夢見自己被關(guān)在監(jiān)獄里 但我一直想不起做錯了什么 夢里還記得進(jìn)過兩次監(jiān)獄 后來有人說我在KTV喝醉了 聽見有人唱歌說我 然后我就把他打了 嚇得我醒了 還在想自己有沒有進(jìn)過監(jiān)獄', '107')
('/users/31854592/', '流云徐徐', '陪4歲蘿莉小侄女去超市買東西,小姑娘見到吃的東西就走不動路了,睜著大眼睛可憐兮兮地看著我讓買零食。我就逗她:“點(diǎn)點(diǎn),叔叔沒錢,買不起?!彪S即大眼睛一陣暗淡,突然又亮起來!只見她跑到導(dǎo)購阿姨那邊跟人聊天,五分鐘以后歡快地帶著阿姨過來。阿姨說:“小姑娘夸了你半天,想把你賣了換零食?!蔽遥骸YI買買,小吃貨從小就惹不起!', '376')
爬取下來的圖片

從上圖可以看到我們已經(jīng)把圖片下載到本地磁盤了。

代碼解析

本次代碼新增了一個正則表達(dá)式,一個目錄創(chuàng)建,一個從通過url地址下載的函數(shù)

  • picture = re.compile(r'<div class="thumb">.?src="(.?)"', re.S):
    該表達(dá)式的作用是匹配到圖片的url地址
  • makedirs:該函數(shù)是創(chuàng)建目錄,于我們在linux系統(tǒng)中執(zhí)行mkdir -p path1/path2/path3的功能是一樣的,它可以層級遞歸的去創(chuàng)建目錄,不需要我們手動每一級每一級的去創(chuàng)建目錄, 看到這里是不是比windows創(chuàng)建目錄方便多了。
  • urlretrieve:該函數(shù)是下載一個網(wǎng)絡(luò)對象到本地文件,該函數(shù)返回一個元組,(local_filename, headers),函數(shù)定義如下:
    urllib.request.urlretrieve(url, filename=None, reporthook=None,data=None)
    url就是我們要從網(wǎng)絡(luò)中下載的文件地址,filename是下載后存放在本地的文件名
  • os.path.basename(pictures[0]):該函數(shù)的作用是返回文件名,什么意思呢,pictures[0]取到是//pic.qiushibaike.com/system/pictures/11966/119663395/medium/app119663395.jpg地址,通過這個函數(shù)處理后我們得到將是app119663395.jpg

note: 作為初學(xué)者,學(xué)習(xí)一種語言就是要不斷的敲代碼,只有通過敲代碼才能發(fā)現(xiàn)問題,然后修正問題,最后才能把別人的東西變成自己的,不然別人的永遠(yuǎn)都是別人的,一定要實踐,切記!切記!

歡迎關(guān)注我:「愛做飯的老謝」,老謝一直在努力...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容