1. 程式人生 > 其它 >【彼岸美圖】二十行程式碼下載上千張高清美圖桌布【python爬蟲】

【彼岸美圖】二十行程式碼下載上千張高清美圖桌布【python爬蟲】

小白也能看懂的python爬蟲,從零開始爬彼岸圖網桌布美圖

你是否有過以下煩惱:

  • 想找桌布卻找不到
  • 找到的桌布清晰度都不高?
  • 下載圖片太麻煩?
    現在,你將可以用簡簡單單二十行程式碼解決這一切煩惱,還不趕快跟我行動起來?
    首先來看一下效果圖吧

    好了,那我們現在開始吧,let's go!!!!!
    首先我們開啟彼岸桌布的網址:! http://www.netbian.com/mei/index.htm
    對於爬蟲,我們拿到一個網站先看看原始碼,看看是否可以直接獲取

    顯然,我們想要的圖片原始碼裡面都有,哈哈,這不就好辦了嗎

既然如此,那我們看看它是怎麼換頁的,我們點到其他頁觀察其url,

第二頁:http://www.netbian.com/mei/index_2.htm


第三頁: http://www.netbian.com/mei/index_3.htm
很明顯,我們知道後面的數字就是彼岸圖網的翻頁規律,那第一頁是不是! http://www.netbian.com/mei/index.htm_1呢,我們不得而知,訪問看看
結果告訴我們,並不是!!!!雖然直接跳轉是可以訪問的,但是在瀏覽器輸入卻不行,那是因為瀏覽器自動跳轉到 http://www.netbian.com/mei/index.htm
因此我們得單獨判斷第一頁的

我們首先寫下爬蟲最基本的一些程式碼

base_url = 'http://www.netbian.com/mei/index.htm'  # 第一頁url
# 一共有165頁,因此我們可以將所有的url先列出來,以便更好的操作
list = [f'http://www.netbian.com/mei/index_{i + 2}.htm' for i in range(164)]  #這是列表推導式,迴圈164次,然後就可以生成164個url了,也就是除了第一頁的所有頁面
list.insert(0, base_url)  # 為了方便,我們將第一頁的url加進其他頁的列表中的第一個位置
headers={
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36'
    }   #這是請求頭,在瀏覽器中就可以找到它

首先我們對第一頁的爬取進行分析
既然我們想要的東西網頁原始碼中都有,那我們可以直接獲取
開啟開發者工具:鍵盤上按下F12或者在頁面空白處單機滑鼠右鍵-->檢查

然後進入到如圖所示介面,先後點選1和2,發現定位到點選圖片的位置處,通過前端程式碼我們發現圖片都在ul標籤中,也就是所有的li標籤,因此我們點開li標籤就可以看到圖片的地址了

然後我們根據img標籤寫xpath表示式://div[@class='list']/ul/li/a/img/@src
通過xpath我們就能得到所有圖片的 url 了,同樣,我們儲存圖片需要對圖片命名,因此我們獲取到圖片的標題://div[@class='list']/ul/li/a/img/@alt
程式碼如下

res=requests.get(url,headers=headers)
    print(res.status_code)
    html = etree.HTML(res.content.decode('gbk'))
    hrefs = html.xpath("//div[@class='list']/ul/li/a/img/@src")   # 獲取連結
    titles = html.xpath("//div[@class='list']/ul/li/a/img/@alt")    # 獲取標題

得到了圖片的連結我們就可以快樂的下載圖片啦

for href, title in zip(hrefs, titles):   # 這個是對連結和標題進行遍歷,得到每一個標題和連結
    with open(f"./圖片/{title}" + '.jpg','wb')as f:  # 這就是儲存圖片咯,如果你想儲存在某個地方,只需要把那個地址與"./圖片"替換就可以了,如果你就想儲存在這兒,你應該在你寫程式碼的同路徑下建立一個名字為圖片的資料夾
    	response=requests.get(href,headers=headers).content
        f.write(response)
        print(title, "------下載完成------")

就這樣,我們就完成了165頁圖片的下載了,是不是很神奇,你的煩惱都沒了吧

完整程式碼如下

import requests
from lxml import etree
from concurrent.futures import ThreadPoolExecutor  # 這是加快程式碼執行速度的

def download(url):  # 寫一個函式封裝程式碼
    headers={
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36'
    }   #請求頭

    res=requests.get(url,headers=headers)  #向網站傳送get請求
    html = etree.HTML(res.content.decode('gbk')) #將字串轉換成element型別
    hrefs = html.xpath("//div[@class='list']/ul/li/a/img/@src") # 獲取圖片連結
    titles = html.xpath("//div[@class='list']/ul/li/a/img/@alt") # 獲取圖片標題
    for href, title in zip(hrefs, titles):
        with open(f"./圖片/{title}" + '.jpg','wb')as f: # wb是二進位制檔案寫入
            response=requests.get(href,headers=headers).content #圖片儲存用二進位制形式
            f.write(response)
            print(title, "------下載完成------")

if __name__ == '__main__':
    base_url = 'http://www.netbian.com/mei/index.htm'
    list = [f'http://www.netbian.com/mei/index_{i + 2}.htm' for i in range(164)]
    list.insert(0, base_url)
    with ThreadPoolExecutor() as pool:    # 這是執行緒池,可以加快程式碼的執行速度
        [pool.submit(download,url) for url in list] # 從list中遍歷取出所有的url然後下載

當然,你可能還會有以下問題

  1. 隨便下載了幾張圖片就再也下不了了
  2. 下載的圖片打不開

這些都是因為IP被封了,所以就訪問不了網站了
因此,為了解決這個問題,我們可以使用代理,也就是用別人的IP,而python使用代理的方法也很簡單,只需要增加幾行程式碼即可

proxies = {
    'http': 'http://'    # 省略號處就是IP啦:IP:埠
    'https': 'https://......'
}

而IP我們可以去哪裡獲取呢?我們可以網上搜索免費IP即可找到很多IP網站,找到免費的就行了,當然免費的能用的只是少數,但為了學習,免費的足夠了
使用IP的方法有很多,為了偷懶,這裡直接把所有的IP寫在程式碼中,關鍵程式碼如下

A=['125.65.16.63:4278','1.70.249.56:4212','111.199.129.47:4212','221.11.234.251:4220','117.94.158.92:4236','117.26.195.72:4213','27.190.82.112:4278','183.32.224.214:4246','117.34.192.155:4210','113.239.159.62:4245']
i=random.choice(A)   # 在A中隨機選擇一個IP
proxies = {
    'http': 'http://'+i,
    'https': 'https://'+i
}
# 傳送get請求時加上代理
response=requests.get(href,proxies=proxies,headers=headers).content

A儲存了要使用的IP,然後每次隨機從A裡面取一個使用

使用代理後的完整程式碼如下,當然沒多大區別

import requests
from lxml import etree
from concurrent.futures import ThreadPoolExecutor
import random


def download(url):
    headers={
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36'
    }
    A=['125.65.16.63:4278','1.70.249.56:4212','111.199.129.47:4212','221.11.234.251:4220','117.94.158.92:4236','117.26.195.72:4213','27.190.82.112:4278','183.32.224.214:4246','117.34.192.155:4210','113.239.159.62:4245']
    i=random.choice(A)
    proxies = {
        'http': 'http://'+i,
        'https': 'https://'+i
    }
    res=requests.get(url,headers=headers)
    print(res.status_code)
    html = etree.HTML(res.content.decode('gbk'))
    hrefs = html.xpath("//div[@class='list']/ul/li/a/img/@src")
    titles = html.xpath("//div[@class='list']/ul/li/a/img/@alt")
    for href, title in zip(hrefs, titles):
        with open(f"./圖片/{title}" + '.jpg','wb')as f:
            response=requests.get(href,proxies=proxies,headers=headers).content
            f.write(response)
            print(title, "------下載完成------")

if __name__ == '__main__':
    base_url = 'http://www.netbian.com/mei/index.htm'
    list = [f'http://www.netbian.com/mei/index_{i + 2}.htm' for i in range(164)]
    list.insert(0, base_url)
    with ThreadPoolExecutor() as pool:
        [pool.submit(download,url) for url in list]

到現在了,是不是沒什麼問題了?

什麼?你找不到IP在哪裡?
下面以芝麻代理為例,芝麻代理每天有20個免費的IP,親測質量也是挺好的,用於學習也夠了

  1. 首先開啟芝麻代理首頁,註冊登入,然後點選HTTP代理
  2. 點選獲取API
  3. 選擇免費的IP
  4. 然後選擇要提取的數量,其他保持預設就行,當然你也可以更改
  5. 然後點選生成API連結,在下面的開啟連結中選擇一個開啟,你就可以看到你提取的IP啦

  6. 最後將這些 IP換在A列表中就可以無限的快樂啦

對於文中提及不懂的可以自行查詢,如有更好的建議,謝謝反饋,歡迎留言