【python--爬蟲】彼岸圖網高清桌布爬蟲

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

前言

你還在為桌布太過老土被盆友嘲笑而苦惱嗎?
你還在為找不到高清桌布而煩惱嗎?
你還在為桌布網站的收費而感到囊中羞澀嗎?
NO,NO,NO!!!
人生苦短,山東數十萌新變身高富帥的夢想,你可以複製!
是時候換個桌布啦!

如有版權問題請聯絡博主,謝謝!展示一張天依小可愛的桌布

前提準備

本次我們要爬取的網站是彼岸圖網,網址連結:http://pic.netbian.com
需要各位讀者大大提前準備好以下環境:
1.python3.7(版本為3的就可以了)
2.火狐瀏覽器(這個版本沒要求)
4.requests庫(這個版本也沒啥要求)
5.lxml庫(博主使用的4.3.3)

網頁分析

我們先開啟彼岸圖網,網址連結:http://pic.netbian.com
在這裡插入圖片描述點選【尺寸】,然後選擇【4K桌布】,就可以開啟這個頁面,
頁面連結:http://pic.netbian.com/e/search/result/?searchid=1224
在這裡插入圖片描述這個頁面上的圖片就是我們要爬取的圖片。我們將這種頁面叫做:主頁面。
往下滑,可以看到一共有535頁
在這裡插入圖片描述我們點選第二頁,看看url有啥變化
在這裡插入圖片描述
再次點選第三頁,
在這裡插入圖片描述
再點選第四頁
在這裡插入圖片描述

發現一個規律,第n頁的url就是
http://pic.netbian.com/e/search/result/index.php?page=n-1&searchid=1224
我們嘗試通過這個規律,看看能不能通過url:
http://pic.netbian.com/e/search/result/index.php?page=0&searchid=1224
開啟第一頁
在這裡插入圖片描述開啟了,頁面內容也是一致的。這麼這個url規律是對的。我們把開啟主頁面的url叫做主頁面url。
現在點選圖片,開啟圖片詳情頁。一般我們把圖片詳情頁叫做子頁面,子頁面的url叫做子url。
演示使用的url是:http://pic.netbian.com/tupian/24455.html
在這裡插入圖片描述右鍵圖片,【檢視元素】可以跳轉到圖片的程式碼處
在這裡插入圖片描述得到了圖片的url: /uploads/allimg/190717/230846-15633761263c79.jpg
發現這個url不是一個完整的url。證明還需要知道一個主url。
注意:這裡說的是主url,不是開啟主頁面的主頁面url。一般網站的主url,就是網站的網址。
比如說當前的這個網站的網址是:http://pic.netbian.com,那麼這個主url就是:http://pic.netbian.com
我們把主url和圖片的url拼接到一起得到一個完整的url。
http://pic.netbian.com/uploads/allimg/190717/230846-15633761263c79.jpg,
在瀏覽器開啟驗證
在這裡插入圖片描述成功開啟了,證明url沒問題。現在再去確認這個url是本來就存在於網頁程式碼中,還是js載入出來的。
先返回子頁面
在這裡插入圖片描述接著在按【ctrl】+【u】,開啟網頁的原始碼。
在這裡插入圖片描述這麼多,一行一行的找肯定不現實,我們使用頁面查詢功能,按【ctrl】+【F】調出查詢功能。
在輸入框中輸入我們之前提取出來的圖片url【/uploads/allimg/190717/230846-15633761263c79.jpg】按確認進行查詢
在這裡插入圖片描述藍色的部分就是找到的網址,可以證明圖片的url就是存在於網頁程式碼中的。

總結下:
主頁面url的規律是:
第n頁的url就是:http://pic.netbian.com/e/search/result/index.php?page=n-1&searchid=1224
由主頁面可以得到圖片詳情頁,我們要爬取的圖片就存在於圖片詳情頁的網頁原始碼中。

實戰程式碼

首先我們在存放程式碼的資料夾中建立一個名為【img】的資料夾用於存放後面爬取到的圖片

1.前提引數
我們先寫上如下程式碼

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

第一行是老生常談的設定程式編碼格式
第二行是記錄作者資訊
第三行是記錄編寫時間

2.匯入模組

from lxml import etree
import requests

第一行的意思是從lxml模組中匯入etree函式,用於解析網頁程式碼,提取出我們想要的資訊
第二行是匯入requests模組,用於獲取網頁程式碼,下載圖片等!

3.常用函式

main_url = 'http://pic.netbian.com'    #主url,用於後期補齊圖片url。

main_page_url = 'http://pic.netbian.com/e/search/result/index.php?page={}&searchid=1224'
#mian_page_url 主頁面url,用於解析獲取圖片詳情頁的url,
#其中{}的作用是使用format函式將內容以字串的形式新增到{}的位置

header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:66.0) Gecko/20100101 Firefox/66.0',}
#請求頭,用於後期訪問網頁,下載圖片

這個我就不解釋了,程式碼中#號後面的註釋就是了!
偷個懶,相信各位大大,不會介意的(〃` 3′〃)

4.網頁請求函式

def get_html(url):
    """定義一個用於獲取網頁程式碼的函式,呼叫時需要傳遞目標url"""
    return requests.get(url,headers=header).content.decode('gbk')

定義一個名為get_html的函式,每次呼叫這個函式時需要傳遞一個url,作為要爬取的網頁。
使用我們前面設定的變數 header作為爬取網頁的請求頭,將爬取到的內容解析為二進位制格式。
使用decode函式將網頁的二進位制資料轉碼為gbk格式的文字資料,並將這個網頁資料作為返回值彈出。

我們來測試下,嘗試獲取第十頁的原始碼

def get_html(url):
    """定義一個用於獲取網頁程式碼的函式,呼叫時需要傳遞目標url"""
    return requests.get(url,headers=header).text
    
html = get_html(main_page_url.format(10))
print (html)

在這裡插入圖片描述出現這個黃顏色的框框是因為要輸出的內容比較長,所以IDLE自動幫我們縮小了,是要雙擊黃顏色的框框就可以將縮略的內容顯示出來。我們雙擊開啟。
在這裡插入圖片描述我們成功的獲取到了網頁程式碼,好棒的!給自己鼓個掌,呱唧呱唧!o( ̄▽ ̄)ブ

5.解析網頁
即然我們將主頁面的原始碼獲取下來了,現在還需要從主頁面的原始碼中解析出來子頁面的url,也就是我們說的圖片詳情頁的url

def get_sub_url(html):
    """從主頁面的原始碼中提取子頁面的url"""
    html_etree = etree.HTML(html)
    sub_url = html_etree.xpath('//ul[@class="clearfix"]/li/a/@href')
    return sub_url

首先我們定義了名為get_sub_url的函式用於從網頁程式碼中獲取子頁面的url,每次呼叫時需要將主頁面的原始碼作為引數傳入。
函式第一行我們將網頁轉為了etree格式的並將之存入變數html_etree
函式第二行我們使用xpath匹配出網頁原始碼中有著屬性為【class=“clearfix”】的ul元素中的
li中的a元素中的href屬性的值,並將匹配出來的url存入了變數sub_url
函式第三行我們將變數sub_url作為返回值彈出程式

我們來驗證下

def get_sub_url(html):
    """從主頁面的原始碼中提取子頁面的url"""
    html_etree = etree.HTML(html)
    sub_url = html_etree.xpath('//ul[@class="clearfix"]/li/a/@href')
    return sub_url

html = get_html(main_page_url.format(0))
urls = get_sub_url(html)
print (urls)

執行效果

['/tupian/24459.html', '/tupian/24458.html', '/tupian/24455.html', '/tupian/24454.html', '/tupian/24453.html',
 '/tupian/24450.html', '/tupian/24452.html', '/tupian/24451.html', '/tupian/18363.html', '/tupian/24031.html',
  '/tupian/24335.html', '/tupian/12356.html', '/tupian/21953.html', '/tupian/24411.html', '/tupian/21449.html', 
  '/tupian/22368.html', '/tupian/17785.html', '/tupian/24440.html', '/tupian/24438.html', '/tupian/24433.html', 
  '/tupian/12072.html']
>>> 

可以看到我們獲取出來的子url是不完整的,還需要補上我們的主url http://pic.netbian.com

6.補齊子頁面url
我們使用一個for 迴圈補齊url

for url in urls:
    sub_page_url = main_url+url
    print (sub_page_url)

執行的效果

http://pic.netbian.com/tupian/24459.html
http://pic.netbian.com/tupian/24458.html
http://pic.netbian.com/tupian/24455.html
http://pic.netbian.com/tupian/24454.html
http://pic.netbian.com/tupian/24453.html
http://pic.netbian.com/tupian/24450.html
http://pic.netbian.com/tupian/24452.html
http://pic.netbian.com/tupian/24451.html
http://pic.netbian.com/tupian/18363.html
http://pic.netbian.com/tupian/24031.html
http://pic.netbian.com/tupian/24335.html
http://pic.netbian.com/tupian/12356.html
http://pic.netbian.com/tupian/21953.html
http://pic.netbian.com/tupian/24411.html
http://pic.netbian.com/tupian/21449.html
http://pic.netbian.com/tupian/22368.html
http://pic.netbian.com/tupian/17785.html
http://pic.netbian.com/tupian/24440.html
http://pic.netbian.com/tupian/24438.html
http://pic.netbian.com/tupian/24433.html
http://pic.netbian.com/tupian/12072.html
>>> 

我們在瀏覽器中開啟第一條url http://pic.netbian.com/tupian/24459.html
在這裡插入圖片描述開啟了,證明這些補齊後的子頁面url是正確的。

7.訪問子頁面
現在我們再獲取子頁面的原始碼,再前面的for迴圈中再新增一行程式碼

sub_html = get_html(sub_page_url)
sub_html = sub_html.encode('utf-8').decode('gbk')

將我們補齊後的子頁面url作為呼叫前面定義的get_html函式的引數,並將下載的網頁儲存到變數sub_html中,我們執行看一下!

html = get_html(main_page_url.format(0))
urls = get_sub_url(html)
for url in urls:
    sub_page_url = main_url+url
    sub_html = get_html(sub_page_url)
    print (sub_html)

執行後的結果
在這裡插入圖片描述8.提取子頁面圖片連結
現在我們也能獲取到了子頁面的原始碼,是時候再編寫一個函式提取出來子頁面中的圖片了
注意這個函式我們要寫到for迴圈之前

def get_img_info(html):
    """從子頁面的原始碼中提取圖片url"""
    html_etree = etree.HTML(html)
    img_url = html_etree.xpath('//div[@class="photo-pic"]/a/img/@src')[0]
    img_title = html_etree.xpath('//div[@class="photo-pic"]/a/img/@title')[0].replace(' ','').replace('《','').replace('》','').replace("(","").replace(")","").replace(":","").replace(":",'')
    return img_url,img_title

我們建立一個名為get_img_info的函式,呼叫該函式時需要傳遞進來圖片詳情頁的原始碼。
函式第一行我們將網頁程式碼轉為為了etree格式的,並將之儲存到函式html_etree中。
函式第二行我們使用xpath匹配出了屬性為【class=“photo-pic”】的【div】元素下的a元素下的img元素的src屬性的值,由於xpath預設匹配出來的值是以列表的格式,所以我們要使用[0]將其匹配出來
並將其儲存到變數img_url中。
函式第三行我們使用xpath匹配出了屬性為【class=“photo-pic”】的【div】元素下的a元素下的img元素的title屬性的值,由於xpath預設匹配出來的值是以列表的格式,所以我們要使用[0]將其匹配出來
由於圖片名稱中可能會有會有多餘的空格,《,》所以我們使用replace函式將他們剔除掉!最後將其儲存到變數img_title中
變數最後一行我們將圖片的url和標題作為函式的執行結果彈出。
執行看下

html = get_html(main_page_url.format(0))
urls = get_sub_url(html)
for url in urls:
    sub_page_url = main_url+url
    sub_html = get_html(sub_page_url)
    img_url,img_title = get_img_url(sub_html)
    full_img_url = main_url + img_url
    print (full_img_url,img_title)

我們將前面下載的子頁面原始碼作為引數傳入了我們定義的函式get_img_url中得到了img_url和img_title,圖片的url和標題。由於圖片的url不是完整的所以引申出了倒數第二行的程式碼,我們將main_url主url和img_url圖片url拼接再一起,得到了完整的圖片url,將其儲存到full_img_url中。
執行後效果:

http://pic.netbian.com/uploads/allimg/190721/220511-156371791196e5.jpg KDADva守望先鋒4k桌布3840x2160
http://pic.netbian.com/uploads/allimg/190721/220015-15637176155637.jpg 阿狸插畫4k原畫桌布
http://pic.netbian.com/uploads/allimg/190717/231857-15633767378c4f.jpg 大宋少年志趙簡劇照4k桌布
http://pic.netbian.com/uploads/allimg/190717/231654-1563376614357e.jpg 大宋少年志王寬的劇照4k桌布
http://pic.netbian.com/uploads/allimg/190717/230846-15633761263c79.jpg 大宋少年志蘇曉彤的劇照4k桌布
http://pic.netbian.com/uploads/allimg/190717/230718-1563376038733a.jpg 大宋少年志周雨彤的劇照4k桌布
http://pic.netbian.com/uploads/allimg/190717/230450-1563375890d74e.jpg 大宋少年志趙簡4k桌布3840x2160
http://pic.netbian.com/uploads/allimg/190713/104025-15629856250f21.jpg 剛起床的美女唯美插畫4k動漫桌布
http://pic.netbian.com/uploads/allimg/190713/104340-1562985820e760.jpg 受傷的天使唯美插畫4k動漫桌布
http://pic.netbian.com/uploads/allimg/190713/104217-156298573792c2.jpg 穿短褲少女唯美藝術插畫4k桌布
http://pic.netbian.com/uploads/allimg/180222/231102-151931226201f1.jpg lol娑娜大胸白絲4k桌布
http://pic.netbian.com/uploads/allimg/190415/214606-15553359663cd8.jpg 女孩微笑蹲著水海岸海灘波浪風夜晚4k動漫桌布
http://pic.netbian.com/uploads/allimg/190614/221508-15605217086e6f.jpg 少女女孩背部寫真唯美藝術插畫4k動漫桌布
http://pic.netbian.com/uploads/allimg/170725/103840-150095032034c0.jpg 布蘭德福德路作者TheWanderingSoul4K風景桌布
http://pic.netbian.com/uploads/allimg/180826/113958-153525479855be.jpg 阿爾卑斯山風景4k高清桌布3840x2160
http://pic.netbian.com/uploads/allimg/190706/165730-15624034501cdb.jpg dva可愛女生裝4k手機桌布豎屏
http://pic.netbian.com/uploads/allimg/180718/135924-15318935643369.jpg 克拉女神江琴居家沙發養眼美腿美女4k桌布
http://pic.netbian.com/uploads/allimg/181004/202029-1538655629aa26.jpg 尤果網美女趙智妍4k桌布
http://pic.netbian.com/uploads/allimg/180128/113416-1517110456633d.jpg 糖果性感美女4k桌布
http://pic.netbian.com/uploads/allimg/190713/100525-15629835259f05.jpg 克拉女神-慕菲含情凝睇4k美女桌布3840x2160
http://pic.netbian.com/uploads/allimg/190713/100152-1562983312a505.jpg 克拉女神-蓓穎風度嫻雅4k美女桌布
>>> 
  1. 下載並儲存圖片
    我們現在獲取了圖片的url和標題的,成敗就看這最後一哆嗦了!
def save(url,title):
    """下載並儲存圖片"""
    img = requests.get(url,headers=header).content
    img_name = 'img/'+title+'.jpg'
    with open (title,'wb') as save_object:
        sasve_object.write(img)

定義了一個函式save,用於下載並儲存引數。呼叫時需要傳遞圖片的url和圖片的名稱。
函式第一行我們使用requests的get方法下載圖片,請求的url是圖片的url,請求頭是我們前面設定的header,將下載到內容以二進位制的形式儲存到變數img中。
函式第二行我們使用’img/’+圖片名稱+’.jpg’儲存到變數img_name中,作為儲存圖片的名稱
倒數兩行我們以二進位制的形式儲存了圖片
執行的結果:
在這裡插入圖片描述
10.爬取全部頁面的圖片
最後我們修改for迴圈,讓程式能爬取全部頁面的圖片。

for number in range(533):
    html = get_html(main_page_url.format(number))
    print ("[+]正在爬取第{}頁".format(number))
    urls = get_sub_url(html)
    for url in urls:
        sub_page_url = main_url+url
        sub_html = get_html(sub_page_url)
        img_url,img_title = get_img_info(sub_html)
        full_img_url = main_url + img_url
        save(full_img_url,img_title)

我們使用for迴圈生成了0到532的數字用於補齊主頁面的url,相當於我們爬取了全部頁面的圖片

完整程式碼

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


from lxml import etree
import requests


main_url = 'http://pic.netbian.com'    #主url,用於後期補齊圖片url。

main_page_url = 'http://pic.netbian.com/e/search/result/index.php?page={}&searchid=1224'
#mian_page_url 主頁面url,用於解析獲取圖片詳情頁的url,
#其中{}的作用是使用format函式將內容以字串的形式新增到{}的位置

header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:66.0) Gecko/20100101 Firefox/66.0',}
#請求頭,用於後期訪問網頁,下載圖片


def get_html(url):
    """定義一個用於獲取網頁程式碼的函式,呼叫時需要傳遞目標url"""
    return requests.get(url,headers=header).content.decode('gbk')



def get_sub_url(html):
    """從主頁面的原始碼中提取子頁面的url"""
    html_etree = etree.HTML(html)
    sub_url = html_etree.xpath('//ul[@class="clearfix"]/li/a/@href')
    return sub_url


def get_img_info(html):
    """從子頁面的原始碼中提取圖片url"""
    html_etree = etree.HTML(html)
    img_url = html_etree.xpath('//div[@class="photo-pic"]/a/img/@src')[0]
    img_title = html_etree.xpath('//div[@class="photo-pic"]/a/img/@title')[0].replace(' ','').replace('《','').replace('》','').replace("(","").replace(")","").replace(":","").replace(":",'')
    return img_url,img_title


def save(url,title):
    """下載並儲存圖片"""
    img = requests.get(url,headers=header).content
    img_name = 'img/'+title+'.jpg'
    with open (img_name,'wb') as save_object:
        save_object.write(img)

for number in range(533):
    html = get_html(main_page_url.format(number))
    print ("[+]正在爬取第{}頁".format(number))
    urls = get_sub_url(html)
    for url in urls:
        sub_page_url = main_url+url
        sub_html = get_html(sub_page_url)
        img_url,img_title = get_img_info(sub_html)
        full_img_url = main_url + img_url
        save(full_img_url,img_title) 

相關文章