【python--爬蟲】千圖網高清背景圖片爬蟲

貓先生的早茶發表於2019-05-21

最近有讀者反映想要下載千圖網的高清背景圖片,但是需要會員才能下載,而且需要的量非常大,問博主有沒有辦法能免費下載這些圖片。
付費,不存在的o( ̄▽ ̄)o!,博主今天講解如何通過python爬取千圖網的高清背景圖片。
快,快,坐好小板凳,拿好小瓜子,聽博主吹牛,額,是講課,講課!╰( ̄ω ̄o)

編寫環境

為了完美食用本篇教程貼,搭建好如下環境
可以上網際網路的win7或win10電腦一臺
火狐瀏覽器(版本無要求)
Python(版本3就可以了)
requests庫(版本沒啥要求)
lxml庫(版本:4.3.3,需要帶有etree的lxml庫)

需求分析

我們本次要爬取的網頁是:千圖網背景圖片模組
在這裡插入圖片描述
我們【右鍵】下面的四張背景圖片中的其中一張,在彈出的選項欄中選擇【檢視元素】,檢視背景圖片的網頁程式碼
在這裡插入圖片描述在這裡插入圖片描述可以看到圖片指向了一個url,我們將這個url複製出來,在新的標籤頁中開啟。看看,是不是到了圖片的高清大圖頁面。
url連結【//www.58pic.com/newpic/33945157.html】
在這裡插入圖片描述可以看到進入了圖片的高清大圖頁面。證明,我們最開始開啟的頁面
https://www.58pic.com/piccate/10-0-0-p1.html】 的原始碼中包含著每張圖片的高清大圖頁面的url。這就說明,我們可以通過爬取最開始開啟的頁面的原始碼進入對應的背景圖片的詳情頁面。(00)/好棒!
我們在看看能不能在背景圖片詳情頁面的原始碼中找到圖片對應的url,如果有url,我們就可以直接請求url下載高清大圖了,就能實現和登陸下載一樣的效果。
【右鍵】圖片,點選【檢視元素】,即可跳轉到網頁原始碼中圖片原始碼的位置
在這裡插入圖片描述開啟後的頁面如下:在這裡插入圖片描述可以看到高清大圖的url存在於頁面的原始碼當中。我們將這個圖片的網址複製出來,在新頁面中開啟看看,是不是對應的這張圖片。
圖片連結【//pic.qiantucdn.com/back_origin_pic/05/63/65/2484f933a50db5e542da4d3a4f1ea31c.jpg!/fw/1024/watermark/url/L2ltYWdlcy93YXRlcm1hcmsvc2h1aXlpbi5wbmc=/repeat/true
在這裡插入圖片描述提示referer頭錯誤,證明下載圖片時,請求頭中需要攜帶referer引數。
那這個referer引數是幹啥的呢(⊙o⊙)?
referer你可以理解為告訴網站伺服器,我是從哪個網頁跳轉過來的。

我們現在總解下上面分析的內容:
1.首先爬取首頁面,比如說這個【https://www.58pic.com/piccate/10-0-0-p1.html 】,首頁面的原始碼中包含有詳情頁的url
2.詳情頁的url中包含有高清大圖的詳細url
3.請求高清大圖的url時需要在請求頭中攜帶referer引數

好膩害,我們居然猜到了網頁設計著的思路╰( ̄ω ̄o)
話不多說,我們來寫python程式碼

實戰程式碼

  1. 前提引數
    首先我們先寫下這些程式碼
# -*- coding:utf-8 -*-
#作者:貓先生的早茶
#時間:2019年5月21日

第一行 # -*- coding:utf-8 -*-的意思時指點該程式使用的utf-8編碼,這個utf-8編碼是幹啥的呢?這裡博主先不做講解,我們先指導程式的開頭需要寫上這句程式碼就可以了。(づ ̄ 3 ̄)づ皮一下,很開心。
第二行和第三行不是必須要寫的,可以省略。。。。

  1. 匯入模組
    我們接在在匯入要使用的模組
import requests
from lxml import etree

這個requests的作用你可以理解為是獲取網頁程式碼的,etree的作用類似於轉換網頁格式,並提取我們想要的資訊。

  1. 設定變數
    我們現在要去設定好接下來會使用到的變數.
main_url = 'https://www.58pic.com/piccate/10-0-0-p1.html'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:66.0) Gecko/20100101 Firefox/66.0',
           'Referer':'https://www.58pic.com/piccate/10-0-0-p1.html',}

這個main_url指的就是我們首先要爬取的主頁面的url,
headers儲存的就是請求頭資訊,什麼是請求頭呢?就是用於告訴伺服器我的資訊,
headers中的User-Agent引數就是告訴伺服器我使用的瀏覽器版本資訊,我使用的這個就是告訴伺服器,我使用的是火狐瀏覽器,是一臺win10,64位的電腦。
headers中的Referer引數用於表示我是從哪個網頁跳轉過去的。

  1. 網頁下載函式
    現在我們先一個函式用於請求網頁程式碼,需要傳遞url作為引數,會將下載到的網頁程式碼作為返回值彈出
def get_html(url):
    '''下載網頁程式碼'''
    html = requests.get(url,headers).text
    return html

我們定義了一個get_html函式專門用於下載網頁程式碼,每次使用這個函式下載網頁程式碼時,需要給其傳遞一個url引數。
函式中,我使用requests庫的get方法下載了網頁的原始碼,get方法使用了變數url和變數headers作為引數,這裡的變數url,就是函式呼叫時傳遞的url引數,headers是我們在步驟2匯入模組中設定的變數,用於作為請求頭,我們講下載到的網頁程式碼的以文字的形式儲存在變數html中,然後講網頁程式碼作為函式的執行結果彈出
我們先測試下執行效果

def get_html(url):
    '''下載網頁程式碼'''
    html = requests.get(url,headers).text
    return html

html = get_html(main_url)
print (html)

在這裡插入圖片描述可以看到,我們成功的下載到了網頁的原始碼,好棒,好棒。鼓掌鼓掌ˋ( ° ▽、° )
現在我們能下載到網頁的原始碼了,還需要提取出來網頁程式碼中圖片的詳情頁面的url

  1. 爬取圖片詳細頁url
def get_page_url(data):
    '''提取詳情頁url'''
    html = etree.HTML(data)
    url_list = html.xpath('//a[@class="thumb-box"]/@href')
    return url_list

這裡我們建立了一個名為get_page_url的函式專門用於提取主頁面原始碼中的圖片詳情頁的url,呼叫該函式時需要將主頁面的原始碼作為引數傳遞進來。
首先我先使用etree.HTML()將傳遞進來的原始碼html,轉換為etree格式的資料,然後使用xpath匹配出了網頁原始碼中的所有圖片詳情頁面的url
為啥xpath後面的括號中要寫【’//a[@class=“thumb-box”]/@href’】呢?,因為在【需求分析】的第二張圖片中講到了,圖片詳情頁的url儲存在主頁面原始碼中class屬性為"thumb-box"的a標籤的href屬性中( •̀ ω •́ )
我們呼叫檢視下效果:

html = get_html(main_url)
url_list = get_page_url(html)
print (url_list)

在這裡插入圖片描述
現在我們獲取到了圖片詳情頁的url了,接著獲取圖片詳情頁的原始碼

  1. 獲取詳情頁原始碼
for url in url_list:
    html=get_html('http:'+url)
    print (html)

使用for迴圈提取出來詳情頁的url,然後使用前面建立的get_html進行下載網頁原始碼,由於獲取到的詳情頁的url缺少字元’http:'所以我使用【‘http’+url】將其補全。
當前我們的程式碼如下:

# -*- coding:utf-8 -*-
#作者:貓先生的早茶
#時間:2019年5月21日

import requests
from lxml import etree

main_url = 'https://www.58pic.com/piccate/10-0-0-p1.html'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:66.0) Gecko/20100101 Firefox/66.0',
           'Referer':'https://www.58pic.com/piccate/10-0-0-p1.html',}

def get_html(url):
    '''下載網頁程式碼'''
    html = requests.get(url,headers).text
    return html

def get_page_url(data):
    '''提取詳情頁url'''
    html = etree.HTML(data)
    url_list = html.xpath('//a[@class="thumb-box"]/@href')
    return url_list

html = get_html(main_url)
url_list = get_page_url(html)
for url in url_list:
    html=get_html('http:'+url)
    print (html)

實現了獲取主頁面的原始碼,然後提取出詳情頁的url,接著在獲取詳情頁的原始碼。
執行後可以看到我們下載到了圖片詳情頁的原始碼了。
在這裡插入圖片描述我們也能獲取詳情頁面的原始碼了,接著就該提取出詳情頁中的高清大圖的url

  1. 獲取高清大圖url和標題
    我們還需要編寫一個函式用於提取高清大圖url和title,url用於作為圖片的下載地址,title用於作為圖片的儲存名稱
def get_img_url(data):
    '''提取高清大圖url'''
    html = etree.HTML(data)
    url = html.xpath('//img[@class="show-area-pic"]/@src')[0]
    title = html.xpath('//img[@class="show-area-pic"]/@title')[0]+'.jpg'
    return url,title

這裡我們建立了一個名為get_img_info的函式專門用於提取詳情頁程式碼中的圖片資訊,包括圖片的url和圖片的標題,呼叫該函式時需要將詳情頁的原始碼作為引數傳遞進來。
首先我先使用etree.HTML()將傳遞進來的原始碼html轉換為etree格式的資料,然後使用xpath匹配出了網頁原始碼中的圖片的url和title
為啥xpath後面要寫[0]呢?,因為xpath預設匹配出的資料是以列表的形式存在的( •̀ ω •́ ),為了將內容提取出來所以要加[0],為啥匹配title的xpath最後面還有 【+‘.jpg’】,應為此時只有檔名,沒有字尾,所以博主這裡使用【+】加號將其拼接成完整的檔名。然後使用return將圖片的url和圖片的名稱傳遞出來。

  1. 下載並儲存圖片
    現在我們也有了圖片的url和名稱了,就差下載儲存圖片了。首先我們在程式所在的建立一個名為 picture 用於儲存下載的圖片。然後編寫一個函式專門用於下載圖片
def get_img(url,file):
    '''下載圖片'''
    file_name = 'picture\\'+file
    img = requests.get(url,headers=headers).content
    with open (file_name,'wb') as save_img:
        save_img.write(img)

這裡我們建立了一個名為get_img的函式專門用於下載圖片,包括下載圖片和儲存圖片到指定目錄下,呼叫該函式時需要將圖片的網址和檔名作為引數傳遞進來。
首先我將儲存的資料夾和檔名合併得到圖片完整的存放路徑,然後使用requests庫的get 方法下載圖片的二進位制資料,將url和headers傳遞給get方法,headers作為get方法的請求頭。將得到的圖片資料儲存到指定的檔案中。

完整程式碼

# -*- coding:utf-8 -*-
#作者:貓先生的早茶
#時間:2019年5月21日

import requests
from lxml import etree

main_url = 'https://www.58pic.com/piccate/10-0-0-p1.html'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:66.0) Gecko/20100101 Firefox/66.0',
           'Referer':'https://www.58pic.com/piccate/10-0-0-p1.html',}

def get_html(url):
    '''下載網頁程式碼'''
    html = requests.get(url,headers).text
    return html

def get_page_url(data):
    '''提取詳情頁url'''
    html = etree.HTML(data)
    url_list = html.xpath('//a[@class="thumb-box"]/@href')
    return url_list

def get_img_url(data):
    '''提取高清大圖url'''
    html = etree.HTML(data)
    url = html.xpath('//img[@class="show-area-pic"]/@src')[0]
    title = html.xpath('//img[@class="show-area-pic"]/@title')[0]+'.jpg'
    return url,title

def get_img(url,file):
    '''下載圖片'''
    file_name = 'picture\\'+file
    img = requests.get(url,headers=headers).content
    with open (file_name,'wb') as save_img:
        save_img.write(img)

html = get_html(main_url)
url_list = get_page_url(html)
for url in url_list:
    html = get_html('http:'+url)
    img_url,img_title = get_img_url(html)
    get_img('http:'+img_url,img_title)
    print ('正在下載{}'.format(img_title))

相關文章