1. 程式人生 > >用python爬取圖片的一點小結

用python爬取圖片的一點小結

一、原理小結

最近在學習用python的爬蟲爬取網路上的圖片,製作資料集並用於後續的一些實驗。看了很多關於python爬取圖片的介紹,並驗證了相關程式碼,先推薦幾個介紹比較好的爬蟲過程:

總體上來說,爬蟲的主要思路大致可以描述為:

1. 判斷待爬取網頁中的圖片是靜態還是動態,並利用開發者選項F12查詢圖片的源

2. python中匯入相關模組,讀取解析頁面檔案

3. 分析所有圖片的位置特點,並用python進行查詢

4. 設定下載路徑,對找到的影象進行批量下載

其中最為關鍵的還是第1步,即對頁面的分析,找到相關的影象位置。

二、動態圖片的爬取

動態圖片是指像百度圖片搜尋,搜狗搜圖等搜尋引擎的搜尋結果,這類圖片的最大特點是,每次只加載一批圖片,每向下拉都會繼續載入新的影象,關於這類圖片的爬取可以參考[3]。這裡

[3]給出一個可以直接執行的程式碼:

# 匯入相關的庫
import requests
import json
import urllib
import os

# 爬取圖片的儲存路徑
output_dir = "./images/"


# 爬取搜狗搜圖的函式
def getSogouImag(category, length, path):
    '''
    引數category:指要爬取圖片的型別,字串格式,如:'桌布'
    引數length:指要爬取多少張,整型
    引數path:儲存路徑
    '''
    n = length
    cate = category
    #http://pic.sogou.com/pics/channel/getAllRecomPicByTag.jsp?category=%E7%BE%8E%E5%A5%B3&tag=%E5%85%A8%E9%83%A8&start=0&len=15
    imgs = requests.get('http://pic.sogou.com/pics/channel/getAllRecomPicByTag.jsp?category='+cate+'&tag=%E5%85%A8%E9%83%A8&start=0&len='+str(n)+'&width=1536&height=864')
    jd = json.loads(imgs.text)
    jd = jd['all_items']
    imgs_url = []
    for j in jd:
        imgs_url.append(j['pic_url'])
    m = 0
    for img_url in imgs_url:
            print('***** '+str(m)+'.jpg *****'+'   Downloading...')
            urllib.request.urlretrieve(img_url, path+str(m)+'.jpg')
            m = m + 1
    print('Download complete!')

# 檢查是否存在路徑,若不存在,則建立
if not os.path.exists(output_dir):
    os.makedirs(output_dir)

# 爬取圖片
getSogouImag('桌布', 1000, output_dir)

修改的話可以修改getSogouImag中的'桌布',將其改為其他型別即可爬取相應的圖片。

爬取的效果圖為:

三、靜態圖片的爬取

靜態圖片是指類似網頁瀏覽圖片那樣,每個頁面僅有一張或者幾張圖片,然後通過點選下一頁來獲取下一個頁面中的圖片。這類圖片的爬取可以參考[2]。這裡[2]給出一個可以直接執行的程式碼:

# 匯入相關的庫
import requests
from bs4 import BeautifulSoup
import os

# 待爬取的網址
all_url = 'http://www.mzitu.com'


# http請求頭,防止反爬蟲
Hostreferer = {
    'User-Agent':'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
    'Referer':'http://www.mzitu.com'
               }
# 此請求頭破解盜鏈
Picreferer = {
    'User-Agent':'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
    'Referer':'http://i.meizitu.net'
}

# 解析頁面
start_html = requests.get(all_url,headers = Hostreferer)

# 爬取圖片的儲存地址
path = 'D:/mzitu/'

#找尋最大頁數
soup = BeautifulSoup(start_html.text,"html.parser")
page = soup.find_all('a',class_='page-numbers')
max_page = page[-2].text


same_url = 'http://www.mzitu.com/page/'
# 逐個爬取套圖
for n in range(1,int(max_page)+1):
    ul = same_url+str(n)
    # 解析頁面
    start_html = requests.get(ul, headers = Hostreferer)
    soup = BeautifulSoup(start_html.text,"html.parser")
    # 找到圖片所在的位置
    all_a = soup.find('div',class_='postlist').find_all('a',target='_blank')
    for a in all_a:
        title = a.get_text()    #提取文字
        if(title != ''):
            print("準備扒取:"+title)

            # win不能建立帶?的目錄
            if(os.path.exists(path+title.strip().replace('?',''))):
                    #print('目錄已存在')
                    flag=1
            else:
                os.makedirs(path+title.strip().replace('?',''))
                flag=0
            os.chdir(path + title.strip().replace('?',''))
            
            # 找到href屬性資訊
            href = a['href']
            html = requests.get(href,headers = Hostreferer)
            mess = BeautifulSoup(html.text,"html.parser")
            pic_max = mess.find_all('span')
            pic_max = pic_max[10].text          #最大頁數
            if(flag == 1 and len(os.listdir(path+title.strip().replace('?',''))) >= int(pic_max)):
                print('已經儲存完畢,跳過')
                continue

            # 爬取套圖中每一頁的圖片
            for num in range(1,int(pic_max)+1):
                pic = href+'/'+str(num)
                html = requests.get(pic,headers = Hostreferer)
                mess = BeautifulSoup(html.text,"html.parser")
                pic_url = mess.find('img',alt = title)
                print(pic_url['src'])
                #exit(0)
                html = requests.get(pic_url['src'],headers = Picreferer)
                file_name = pic_url['src'].split(r'/')[-1]
                
                # 儲存結果
                f = open(file_name,'wb')
                f.write(html.content)
                f.close()
            print('完成')
    print('第',n,'頁完成')

該程式碼可直接執行,爬取的最終結果就不再展示。