Python爬蟲,高清美圖我全都要(彼岸桌面桌布)

索兒呀發表於2020-03-30

本人比較喜歡收集桌布,發現彼岸桌面桌布唯美分類下的桌布,我都很喜歡;於是寫了個爬蟲,後來發現整個網站的網頁結構基本一致,於是加了點程式碼,把整個網頁的高清桌布都爬下來了

目錄一:概覽

在電腦上,建立一個資料夾用來存放爬取彼岸桌面的圖片
Python爬蟲,高清美圖我全都要(彼岸桌面桌布)

此資料夾下有25個資料夾,對應分類
在這裡插入圖片描述
每個分類資料夾下有若干個資料夾,對應頁碼
在這裡插入圖片描述
頁碼資料夾下,存放圖片檔案

目錄二:環境準備

還需要使用三個第三方包(有興致的可以看看官方文件)

  • requests:通過http請求獲取頁面,官方文件
  • lxml:是python的一個解析庫,支援HTML和XML的解析,支援XPath解析方式,而且解析效率非常高,官方文件
  • Beautiful Soup4:可以從HTML或XML檔案中提取資料,官方文件

在終端中分別輸入以下pip命令,安裝它們

python -m pip install beautifulsoup4
python -m pip install lxml
python -m pip install requests

  • 注意:光理論是不夠的。這裡送大家一套2020最新企業Pyhon專案實戰視訊教程,點選此處 進來獲取 跟著練習下,希望大家一起進步哦!

目錄三:分析頁面結構

  • 因為我的電腦的解析度為1920 × 1080,所以我爬取的圖片的解析度為此
  • 彼岸桌面桌布提供了許多分類供我們瀏覽:日曆、動漫、風景、美女、遊戲、影視、動態、唯美、設計…
    Python爬蟲,高清美圖我全都要(彼岸桌面桌布)
    4k分類下的桌布是該網站收益的重要資源,而且我沒有4k桌布的需求,對其不進行爬取
    Python爬蟲,高清美圖我全都要(彼岸桌面桌布)
    CSS選擇器:#header > div.head > ul > li:nth-child(1) > div > a,定位到包裹分類的a標籤

我以唯美分類下的桌布,來講解接下來怎麼爬取圖片
在這裡插入圖片描述

  1. 總共有73頁,除了最後一頁,每頁有18張圖片
    Python爬蟲,高清美圖我全都要(彼岸桌面桌布)
    但是在程式碼中我們最好需要自動獲取總頁碼,嗯,彼岸桌面桌布網站的結構是真的舒服,基本上每個頁碼的HTML結構都是類似的
    Python爬蟲,高清美圖我全都要(彼岸桌面桌布)
    CSS選擇器:div.page a,定位到包裹頁碼數的a標籤,只有6個
  2. 並且每頁的第三張圖片都是一樣的廣告,需要在程式碼中把它過濾掉
  3. 每個分頁的超連結很清晰:http://www.netbian.com/weimei/index_x.htm
    x 恰好為該頁的頁碼
  4. 注意:在分類下看到的圖片是略縮圖,解析度都較低;要得到1920 × 1080解析度的該圖,需要進行兩次跳轉

以下圖為例
Python爬蟲,高清美圖我全都要(彼岸桌面桌布)
在分類頁面中我們可以直接獲取該圖片的url,但很可惜,它的解析度並不令人滿意;
通過檢查,很明顯的看到,在分類頁中展示的每一個圖片都指向另一個超連結
在這裡插入圖片描述
CSS選擇器:div#main div.list ul li a,定位到包裹圖片的a標籤
點選該圖片,第一次跳轉,轉到新的連結,頁面中顯示有下列內容:
在這裡插入圖片描述
CSS選擇器:div#main div.endpage div.pic div.pic-down a,定位到包裹圖片的a標籤

點選下載桌布(1920 × 1080)的按鈕,第二次跳轉,轉向一個新的連結,終於達成目的,該連結中顯示的圖片的解析度為 1920 × 1080

一波三折,終於給我找到了該圖片的1920 × 1080高清圖

CSS選擇器:div#main table a img,定位到該圖片的img標籤

經過本人爬取檢驗,其中有極個別圖片由於很多零碎的問題而下載失敗,還有少部分圖片因為網站雖然提供1920 × 1080解析度的下載按鈕卻給的其它解析度

目錄四:程式碼分析

  • 下文中凡是 紅色加粗內容,請按照我的解釋,根據自身情況進行修改

第一步:設定全域性變數

index = 'http://www.netbian.com' # 網站根地址
interval = 10 # 爬取圖片的間隔時間
firstDir = 'D:/zgh/Pictures/netbian' # 總路徑
classificationDict = {} # 存放網站分類子頁面的資訊
  • index ,要爬取網頁的網站根地址,程式碼中爬取圖片需要使用其拼接完整url
  • interval,我們去爬取一個網站的內容時要考慮到該網站伺服器的承受能力,短時間內爬取該網站大量內容會給該網站伺服器造成巨大壓力,我們需要在爬取時設定間隔時間
    單位:秒
    由於我要爬取彼岸桌面網站的全部高清圖片,若集中在短時間內爬取,一方面會給網站伺服器巨大的壓力,一方面網站伺服器會將我們的連結強制斷掉,所以我設定的每張圖片爬取時間間隔為10秒;如果你只是爬取少量圖片,可以將間隔時間設定的短點
  • firstDir,爬取圖片存放在你電腦上的根路徑;程式碼中爬取圖片時,在一級目錄下會按照彼岸桌面唯美分類下的分頁頁碼生成資料夾並存放圖片
  • classificationDict,存放網站下分類指向的url、對應的分類資料夾路徑

第二步:獲取頁面篩選後的內容列表

寫一個函式,獲取頁面篩選後的內容陣列

  • 傳進來兩個引數
    url:該網頁的url
    select:選擇器(與CSS中的選擇器無縫對接,我很喜歡,定位到HTML中相應的元素)
  • 返回一個列表
def screen(url, select):
    html = requests.get(url = url, headers = UserAgent.get_headers()) # 隨機獲取一個headers
    html.encoding = 'gbk'
    html = html.text
    soup = BeautifulSoup(html, 'lxml')
    return soup.select(select)
  • headers,作用是假裝是個使用者訪問該網站,為了保證爬蟲的成功率,每一次爬取頁面隨機抽取一個headers
  • encoding ,該網站的編碼
    Python爬蟲,高清美圖我全都要(彼岸桌面桌布)

第三步:獲取全部分類的url

# 將分類子頁面資訊存放在字典中
def init_classification():
    url = index
    select = '#header > div.head > ul > li:nth-child(1) > div > a'
    classifications = screen(url, select)
    for c in classifications:
        href = c.get('href') # 獲取的是相對地址
        text = c.string # 獲取分類名
        if(text == '4k桌布'): # 4k桌布,因許可權問題無法爬取,直接跳過
            continue
        secondDir = firstDir + '/' + text # 分類目錄
        url = index + href # 分類子頁面url
        global classificationDict
        classificationDict[text] = {
            'path': secondDir,
            'url': url
        }

接下來的程式碼,我以唯美分類下的桌布,來講解怎麼通過跳轉兩次連結爬取高清圖片

第四步:獲取分類頁面下所有分頁的url

大部分分類的分頁大於等於6頁,可以直接使用上面定義的screen函式,select定義為div.page a,然後screen函式返回的列表中第6個元素可以獲取我們需要的最後一頁頁碼

但是,有的分類的分頁小於6頁,
比如:
Python爬蟲,高清美圖我全都要(彼岸桌面桌布)

需要重新寫一個篩選函式,通過兄弟元素來獲取

# 獲取頁碼
def screenPage(url, select):
    html = requests.get(url = url, headers = UserAgent.get_headers())
    html.encoding = 'gbk'
    html = html.text
    soup = BeautifulSoup(html, 'lxml')
    return soup.select(select)[0].next_sibling.text

獲取分類頁面下所有分頁的url

url = 'http://www.netbian.com/weimei/'
select = '#main > div.page > span.slh'
pageIndex = screenPage(secondUrl, select)
lastPagenum = int(pageIndex) # 獲取最後一頁的頁碼
for i in range(lastPagenum):
    if i == 0:
        url = 'http://www.netbian.com/weimei/index.htm'
    else:
        url = 'http://www.netbian.com/weimei/index_%d.htm' %(i+1)

由於該網站的HTML結構非常清晰,所以程式碼寫起來簡單明瞭

第五步:獲取分頁下圖片所指url

通過檢查,可以看到獲取到的url為相對地址,需要將其轉化為絕對地址
Python爬蟲,高清美圖我全都要(彼岸桌面桌布)

select = 'div#main div.list ul li a'
imgUrls = screen(url, select)

通過這兩行程式碼獲取的列表中的值,形如此:

<a href="/desk/21237.htm" target="_blank" title="星空 女孩 觀望 唯美夜景桌布 更新時間:2019-12-06"><img alt="星空 女孩 觀望 唯美夜景桌布" src="http://img.netbian.com/file/newc/e4f018f89fe9f825753866abafee383f.jpg"/><b>星空 女孩 觀望 唯美夜景桌布</b></a>
  • 需要對獲取的列表進行處理
  • 獲取a標籤中的href屬性值,並將其轉化為絕對地址,這是第一次跳轉所需要的url

第六步:定位到 1920 × 1080 解析度圖片

# 定位到 1920 1080 解析度圖片               
def handleImgs(links, path):
    for link in links:
        href = link.get('href')
        if(href == 'http://pic.netbian.com/'): # 過濾圖片廣告
            continue

        # 第一次跳轉
        if('http://' in href): # 有極個別圖片不提供正確的相對地址
            url = href
        else:
            url = index + href
        select = 'div#main div.endpage div.pic div.pic-down a'
        link = screen(url, select)
        if(link == []):
            print(url + ' 無此圖片,爬取失敗')
            continue
        href = link[0].get('href')

        # 第二次跳轉
        url = index + href

        # 獲取到圖片了
        select = 'div#main table a img'
        link = screen(url, select)
        if(link == []):
            print(url + " 該圖片需要登入才能爬取,爬取失敗")
            continue
        name = link[0].get('alt').replace('\t', '').replace('|', '').replace(':', '').replace('\\', '').replace('/', '').replace('*', '').replace('?', '').replace('"', '').replace('<', '').replace('>', '')
        print(name) # 輸出下載圖片的檔名
        src = link[0].get('src')
        if(requests.get(src).status_code == 404):
            print(url + ' 該圖片下載連結404,爬取失敗')
            print()
            continue
        print()
        download(src, name, path)
        time.sleep(interval)

第七步:下載圖片

# 下載操作
def download(src, name, path):
    if(isinstance(src, str)):
        response = requests.get(src)
        path = path + '/' + name + '.jpg'
        while(os.path.exists(path)): # 若檔名重複
            path = path.split(".")[0] + str(random.randint(2, 17)) + '.' + path.split(".")[1]
        with open(path,'wb') as pic:
            for chunk in response.iter_content(128):
                pic.write(chunk)

目錄五:程式碼的容錯能力

一:過濾圖片廣告

if(href == 'http://pic.netbian.com/'): # 過濾圖片廣告
    continue

二:第一次跳轉頁面,無我們需要的連結

彼岸桌布網站,對第一次跳轉頁面的連結,給的都是相對地址

但是極個別圖片直接給的絕對地址,而且給的是該分類網址,所以需要做兩步處理

if('http://' in href):
    url = href
else:
    url = index + href

...

if(link == []):
    print(url + ' 無此圖片,爬取失敗')
    continue

下面是第二次跳轉頁面所遇問題

三:由於許可權問題無法爬取圖片

if(link == []):
    print(url + "該圖片需要登入才能爬取,爬取失敗")
    continue

四:獲取img的alt,作為下載圖片檔案的檔名時,名字中攜帶\t 或 檔名不允許的特殊字元:

  • 在Python中,’\t’ 是轉義字元:空格
  • 在windows系統當中的檔案命名,檔名稱中不能包含 \ / : * ? " < > | 一共9個特殊字元
    Python爬蟲,高清美圖我全都要(彼岸桌面桌布)
name = link[0].get('alt').replace('\t', '').replace('|', '').replace(':', '').replace('\\', '').replace('/', '').replace('*', '').replace('?', '').replace('"', '').replace('<', '').replace('>', '')

五:獲取img的alt,作為下載圖片檔案的檔名時,名字重複

path = path + '/' + name + '.jpg'
while(os.path.exists(path)): # 若檔名重複
    path = path.split(".")[0] + str(random.randint(2, 17)) + '.' + path.split(".")[1]

六:圖片連結404

比如:
在這裡插入圖片描述

if(requests.get(src).status_code == 404):
    print(url + ' 該圖片下載連結404,爬取失敗')
    print()
    continue

目錄六:完整程式碼

  • 藍奏雲連結:Python爬蟲,高清美圖我全都要(彼岸桌面桌布).zip
    下載下來解壓後,有兩個python檔案
    在這裡插入圖片描述
  • 兄弟們,求求你們別白嫖了,拿走程式碼之前可以點個贊嗎?
    • 截至2020年4月17日,程式碼下載次數227次,點贊收藏數寥寥無幾,博主要哭了
    • 截至2020年5月7日,程式碼下載次數488次,點贊收藏數也非常可觀,感謝大家的支援

  • 注意:光理論是不夠的。這裡送大家一套2020最新企業Pyhon專案實戰視訊教程,點選此處 進來獲取 跟著練習下,希望大家一起進步哦!

相關文章