爬蟲養成記--順藤摸瓜回首掏(女生定製篇)

本文由圖雀社區成員 燦若星空 寫作而成,歡迎加入圖雀社區,一起創作精彩的免費技術教程,予力編程行業發展。

如果您覺得我們寫得還不錯,記得 點贊 + 關注 + 評論 三連🥰🥰🥰,鼓勵我們寫出更好的教程💪

前情回顧

在上篇教程爬蟲養成記——先跨進這個精彩的世界(女生定製篇)中我們已經可以將所有小哥哥的封面照片抓取下來,但僅僅是封面圖片在質量和數量上怎麼能滿足小仙女們的要求呢?在本篇教程中,我們串起一根姻緣“線”,來把這一系列的小哥哥們都收入囊中。

出門先化妝

小仙女們出門約會總會“淡妝濃抹總相宜”,那爬蟲出門去爬取數據,也得打扮打扮啊,不然怎麼能讓男神們都乖乖地跟着走呢?

爬蟲的“化妝”可不是“妝前乳 --> 粉底 --> 遮瑕 --> 散粉 --> 畫眉 --> 口紅”等這些步驟,其目的是爲了讓對方網站更加確信來訪者不是爬蟲程序,而是一個活生生的人。人們通過操控瀏覽器來訪問網站,那麼爬蟲程序只需要模仿瀏覽器就可以了。 那就來看看瀏覽器在打開網頁時都畫了那些“妝”。
在這裏插入圖片描述
打開Chrome並打開調試臺,切換到NetWork選項卡,此時訪問 https://www.nanrentu.cc/sgtp/, 這是時候會看到調試臺裏出現了很多鏈接信息,這麼多鏈接到底哪個是我們所需要的呢?回想一下上一篇內容,首先是要獲得HTML文檔,再從此文檔中提取出圖片的鏈接,所以目標有了,就是找到瀏覽器獲取到這個HTML文檔的那個鏈接。

Chrome知道這麼多鏈接信息肯定會讓開發者陷入茫然,所以給鏈接進行了歸類,點擊上方Doc分類,再點擊那唯一的一條鏈接,就會看到獲取此HTML文檔鏈接的詳細信息了。此時我們關注主要Request Headers 這個裏面的內容。瀏覽器通過http協議與服務器交互獲取信息,爬蟲是通過模仿瀏覽器發出http協議獲取信息,其中最重要的一個模仿點就是Request Headers。

http協議裏面的“瓶瓶罐罐”

讓男生看女孩子化妝用的那些瓶瓶罐罐估計會陷入沉思,這是BB霜,那是粉底液,還有散粉、眼影、遮瑕膏,更不用說各種色號的口紅啦。那女孩子看到這http裏面的各項內容時估計也會一臉懵逼,其這比化妝品簡單多了,我們只需簡單瞭解,就能給爬蟲畫出精緻妝容。

:authority: www.nanrentu.cc
:method: GET   // 自定義請求頭 請求方法
:path: /sgtp/  // 自定義請求頭 請求路徑
:scheme: https // 自定義請求頭 請求方式
// 所接受的內容格式
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
// 所接受的編碼方式
accept-encoding: gzip, deflate, br
// 所接受的語言
accept-language: zh-CN,zh;q=0.9
// 緩存控制:告訴服務器客戶端希望得到一個最新的資源
cache-control: max-age=0
cookie: UM_distinctid=170a5a00fa25bf-075185606c88b7-396d7407-100200-170a5a00fa3507; Hm_lvt_45e50d2aec057f43a3112beaf7f00179=1583326696,1583756661; CNZZDATA1274895726=1196969733-1583323670-%7C1583752625; Hm_lpvt_45e50d2aec057f43a3112beaf7f00179=1583756721
sec-fetch-dest: document
sec-fetch-mode: navigate
sec-fetch-site: none
sec-fetch-user: ?1
// 屏蔽HTTPS頁面出現HTTP請求警報
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36

這麼多的信息不用都給爬蟲加上,因爲這網站的防爬措施等級不高,暫時只要關鍵的兩個就可以了。

  • cookie: 這是存儲在瀏覽器裏面一段文本,有時包含了驗證信息和一些特殊的請求信息
  • user-agent:用於標識此請求是由什麼工具所發出的
    關於User-Agent的詳細信息可以參考此篇博文 談談 UserAgent 字符串的規律和僞造方法

但是當爬取其他網站時可能會有所需要,在這裏贅述這麼多原因就是希望大家能明白僞裝爬蟲的重要性,以及怎麼獲取這些僞裝信息。

// 建立一個名叫headers的字典
headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36',
    'cookie': 'UM_distinctid=170a5a00fa25bf-075185606c88b7-396d7407-100200-170a5a00fa3507; CNZZDATA1274895726=1196969733-1583323670-%7C1583925652; Hm_lvt_45e50d2aec057f43a3112beaf7f00179=1583326696,1583756661,1583926583; Hm_lpvt_45e50d2aec057f43a3112beaf7f00179=1583926583'
}
// 發送請求時帶上請求頭
response = requests.get(baseUrl,headers=headers)

順藤摸瓜

一個網站是由若干個網頁組合而成的,網頁中充滿着各種超鏈接,從這網頁鏈接到那個網頁,如果我們想要更多小哥哥,那就得首先分析出串聯起他們那些超鏈接,然後就可以順藤摸瓜咯。
在這裏插入圖片描述
當把鼠標發放到標題上時,標題的顏色發生了變化,證明這一元素爲超連接,點擊標題瀏覽器會自動打開一個tab標籤頁,來顯示網頁,注意到下方的頁碼標籤,是這些元素串聯起了整個圖集。
在這裏插入圖片描述
點擊“末頁”觀察url發生了什麼變化

末頁的url:https://www.nanrentu.cc/sgtp/36805_7.html

首頁的url:https://www.nanrentu.cc/sgtp/36805.html

看起來有點意思了,末頁的url比首頁的url多了“_7”,接下來再點擊分別進入第2頁,第3頁……觀察url的變化,可得出下表。

頁面 url
首頁 https://www.nanrentu.cc/sgtp/36805.html
第2頁 https://www.nanrentu.cc/sgtp/36805_2.html
第3頁 https://www.nanrentu.cc/sgtp/36805_3.html
第4頁 https://www.nanrentu.cc/sgtp/36805_4.html
第5頁 https://www.nanrentu.cc/sgtp/36805_5.html
第6頁 https://www.nanrentu.cc/sgtp/36805_6.html
第7頁 https://www.nanrentu.cc/sgtp/36805_7.html

多點幾個組圖,也會發現同樣規律。這樣就明瞭很多了,我們已經分析清楚了這個跟“藤”的開頭與結尾,接下來就可以敲出代碼讓爬蟲開始“摸瓜”咯。

摸瓜第1步:提取標題鏈接

這個操作與上篇博文中所介紹的一樣,打開調試臺切換到Elements選項卡就能開始探索提取了。
在這裏插入圖片描述

摸瓜第2步:提取末頁鏈接,得出組圖頁數

在這裏插入圖片描述
通過觀察HTML元素結構,可發現包含末頁的 <li> 標籤爲其父元素<ul>的倒數第二個子元素,所以可得出以下的css選擇器

.page > ul > li:nth-last-child(2) > a

摸瓜第3步:根據首尾鏈接構造url

爲了構造url更加方便,我們可以把首頁 https://www.nanrentu.cc/sgtp/36805.html 變爲 https://www.nanrentu.cc/sgtp/36805_1.html, 在瀏覽器中打開帶有後綴的這個網址,依然能夠成功訪問到首頁,不要問我爲什麼?這可能就是程序員之間的一種默契吧~

摸瓜第4步:存儲圖片,摸瓜成功

完整的代碼如下:


import requests
from pyquery import PyQuery as pq
import uuid

headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36',
    'cookie': 'UM_distinctid=170a5a00fa25bf-075185606c88b7-396d7407-100200-170a5a00fa3507; CNZZDATA1274895726=1196969733-1583323670-%7C1583925652; Hm_lvt_45e50d2aec057f43a3112beaf7f00179=1583326696,1583756661,1583926583; Hm_lpvt_45e50d2aec057f43a3112beaf7f00179=1583926583'
}
def saveImage(imgUrl,name):
    imgResponse = requests.get(imgUrl)
    fileName = "學習文件/%s.jpg" % name
    if imgResponse.status_code == 200:
        with open(fileName, 'wb') as f:
            f.write(imgResponse.content)
            f.close()

def getPic(urlArray):
    for url in urlArray:
        res = requests.get(url,headers=headers)
        if res.status_code == 200:
            doc = pq(res.text)
            imgSrc = doc('.info-pic-list > a > img').attr('src')
            print(imgSrc)
            saveImage(imgSrc,uuid.uuid1().hex)
    

def createUrl(indexUrl,allPage):
    baseUrl = indexUrl.split('.html')[0]
    urlArray = []
    for i in range(1,allPage):
        tempUrl = baseUrl+"_"+str(i)+".html"
        urlArray.append(tempUrl)
    return urlArray

def getBoys(link):
    # 摸瓜第1步:獲取首頁連接
    picIndex = link.attr('href')
    #  摸瓜第2步:打開首頁,提取末頁鏈接,得出組圖頁數
    res = requests.get(picIndex,headers=headers)
    print("當前正在抓取的 picIndex: " + picIndex)
    if res.status_code == 200:
        with open("picIndex.html",'w',encoding="utf-8") as f:
            f.write(res.text)
        doc = pq(res.text)
        lastLink = doc('.page > ul > li:nth-last-child(2) > a').attr('href')
        # 字符串分割,得出全部的頁數
        if(lastLink is None):
            return
        # 以.html 爲分割符進行分割,取結果數組中的第一項
        temp = lastLink.split('.html')[0]
        # 再以下劃線 _ 分割,取結果數組中的第二項,再轉爲數值型
        allPage = int(temp.split('_')[1])
        # 摸瓜第3步:根據首尾鏈接構造url
        urlArray = createUrl(picIndex,allPage)
        # 摸瓜第4步:存儲圖片,摸瓜成功
        getPic(urlArray)

def main():
    baseUrl = "https://www.nanrentu.cc/sgtp/"
    response = requests.get(baseUrl,headers=headers)
    if response.status_code == 200:
        with open("index.html",'w',encoding="utf-8") as f:
            f.write(response.text)
        doc = pq(response.text)
        # 得到所有圖集的標題連接
        titleLinks = doc('.h-piclist > li > a').items()
        # 遍歷這些連接
        for link in titleLinks:
            getBoys(link)

if __name__ == "__main__":
    main()

運行結果:
在這裏插入圖片描述

回首掏

回顧整個爬蟲程序,它是連續式流水線作業,每一步之間都是環環相扣,所以在寫程序前自己一定要把整個流水線的每個環節都考慮清楚,把它們之間的順序依賴關係化成一個簡易的流程圖,對着流程圖再寫程序就會清晰很多。我們可以把每一個模塊都寫成一個函數,先對函數做好單元測試,再把這些函數按順序組合起來就行啦。分而治之,有機組合這就是編程的奧義。再複雜的項目,都是由一個個模塊組建起來的,這和搭積木是一樣的道理。

8eoaDA.png

這個流程圖只用單項箭頭畫出了獲取一張圖片的全部過程,這就相當於一個工人在幹活,我們的計算機是一個大工廠裏面有成千上萬個工人,只讓一個工人幹活其他的人都在爲他加油嘛?那也太說不過去,在下一篇文章中,我們將畫出完整的流程圖,分析出其他工人沒活幹的原因,然後充分調動起計算機的算力,來提升程序的運行效率。

如果您覺得我們寫得還不錯,記得 點贊 + 關注 + 評論 三連🥰🥰🥰,鼓勵我們寫出更好的教程💪

想要學習更多精彩的實戰技術教程?來圖雀社區逛逛吧。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章