批次下載 Pinterest 圖片
Pinterest 是一個收集圖片與點子的平台,瀏覽 Pinterest 的內容時,除了必須登入,還必須捲動頁面才能瀏覽全部的圖片,這篇文章會使用 Python 的 Requests 和 Selenium 函式庫,實作一個會自動瀏覽 Pinterest 頁面的爬蟲,並在瀏覽後自動下載所有圖片在 Pinterest 的原始檔。
執行 selenium 會啟動 chromedriver,所以所以請使用本機環境 ( 參考:使用 Python 虛擬環境 ) 或使用 Anaconda Jupyter 進行實作 ( 參考:使用 Anaconda ) 。
取得 Pinterest 收藏庫有幾個釘圖
開啟一個 Pinterest 的收藏庫,用滑鼠在「X 個釘圖」的位置按下右鍵,選擇「檢查」。
開啟 Chrome 開發者工具後,可以看見「X 個釘圖」位於一個有 data-test-id 屬性的 div 裡。
知道位置後,開始撰寫 Python 程式,使用 Selenium 函式庫,透過 find_element(By.CSS_SELECTOR, selector) 的方法取得該 div,接著將內容根據「空白」拆成前後兩個部分,將前面的部分轉換成數字,執行後,就會印出這個收藏庫的數量。
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome('./chromedriver')
driver.get('https://www.pinterest.com/oxxostudio/outdoor/')
imgCount = driver.find_element(By.CSS_SELECTOR, 'div[data-test-id="pin-count"]')
count = int(imgCount.text.split(' ')[0]) # 拆分字串,取出前方的數字
print(count) # 印出 33
取得 Pinterest 收藏庫所有圖片的網址
因為 Pinterest 在瀏覽時,會「不斷更新頁面的圖片」,過某個範圍的圖片就會消失,以保持瀏覽畫面上下出現固定張數的圖片 ( 目的可能為了節省網站流量、提升速度 ),所以必須使用 selenium 函式庫模擬使用者捲動頁面,在捲動過程中,不斷記錄出現的圖片網址,當圖片數量與收藏庫的數量相同時就停止。
用滑鼠在任意圖片上方按下右鍵,選擇「檢查」。
開啟 Chrome 開發者工具後,可以看見圖片的 tag,圖片位於一個屬性 data-test-id="pin-count" 的 div 裡。
知道圖片的位置後,就能透過程式取得該名稱下的圖片網址 ( src ),將網址一一存入 imgList 的串列中,存入時可先檢查該網址是否已經存在,當存入的數量抵達收藏庫的數量時,就停止並印出存入的內容。
參考:使用 global 修改全域變數、搭配 JavaScript,發揮最大效益、定義函式、例外處理 ( try、except )、while 迴圈
from selenium import webdriver
from selenium.webdriver.common.by import By
from time import sleep
driver = webdriver.Chrome('./chromedriver')
driver.get('https://www.pinterest.com/oxxostudio/outdoor/')
imgCount = driver.find_element(By.CSS_SELECTOR, 'div[data-test-id="pin-count"]')
count = int(imgCount.text.split(' ')[0])
print(count)
imgList = [] # 建立變數,紀錄圖片網址的空串列
scroll = 0 # 建立變數,記錄網頁捲動的高度
def getImg():
global imgList, scroll # 宣告這兩個變數是使用全域變數
scroll = scroll + 450 # 每次執行函式時,捲動增加 450 ( 依據個人頁面大小決定 )
driver.execute_script(f'window.scrollTo(0, {scroll})') # 讓頁面自動捲動
sleep(0.5) # 暫停 0.5 秒,等待畫網頁面更新
imgs = driver.find_elements(By.CSS_SELECTOR, 'div[data-test-id="pin-count"]') # 尋找圖片
for i in imgs:
try:
url = i.get_attribute('src') # 取得圖片網址
if url not in imgList and len(imgList) < count: # 如果數量尚未抵達收藏庫數量,且 imgList 裡沒有這個網址
imgList.append(url) # 存入網址
except:
continue
while True:
getImg() # 不斷執行函式
if len(imgList) >= count: # 直到存入的數量等於收藏庫數量為止
break
print(imgList) # 印出存入的內容
print(len(imgList)) # 印出數量
完成後執行程式,就會印出相關的內容。
批次下載 Pinterest 原始圖片
剛剛存入的圖片網址為「預覽圖」的網址,預覽圖和原始圖片網址的網址差異如下,只要將網址的「236x」改為「originals」就能取得原始圖片 ( 原始圖片的網址也是透過 Chrome 開發者工具取得 ):
預覽圖:https://i.pinimg.com/236x/bb/2a/fd/bb2afd1144cd459ee2b0ff3f1afe7a29--beach-shower-sprites.jpg
原始圖:https://i.pinimg.com/originals/bb/2a/fd/bb2afd1144cd459ee2b0ff3f1afe7a29--beach-shower-sprites.jpg
使用 Requests 和 concurrent.futures 內建函式庫,就能夠批次下載所有原始圖片。
from selenium import webdriver
from selenium.webdriver.common.by import By
from time import sleep
import requests # 使用 Requests 函式庫
from concurrent.futures import ThreadPoolExecutor # 使用 concurrent.futures 函式庫
driver = webdriver.Chrome('./chromedriver')
driver.get('https://www.pinterest.com/oxxostudio/outdoor/')
imgCount = driver.find_element(By.CSS_SELECTOR, 'div[data-test-id="pin-count"]')
count = int(imgCount.text.split(' ')[0])
print(count)
imgList = []
scroll = 0
def getImg():
global imgList, scroll
scroll = scroll + 450
driver.execute_script(f'window.scrollTo(0, {scroll})')
sleep(0.5)
imgs = driver.find_elements(By.CSS_SELECTOR, 'div[data-test-id="pin"] img')
for i in imgs:
try:
url = i.get_attribute('src')
if url not in imgList and len(imgList) < count:
imgList.append(url)
except:
continue
while True:
getImg()
if len(imgList) >= count:
break
print(imgList)
print(len(imgList))
def download(src):
url = src.replace('236x','originals') # 更換網址,將 236x 更換成 originals
name = url.split('/')[::-1][0].split('.jpg')[0].split('--')[0] # 取得圖片名稱
jpg = requests.get(url) # 取得圖片內容
f = open(f'./demo/{name}.jpg', 'wb') # 使用二進位方式開啟圖片準備寫入
f.write(jpg.content) # 存入圖片
f.close()
executor = ThreadPoolExecutor() # 建立非同步的多執行緒的啟動器
with ThreadPoolExecutor() as executor:
executor.map(download, imgList) # 同時下載圖片
小結
Pinterest 不只是非常有名的圖片收集平台,它的網頁也是很不錯的動態網頁練習範本,因為網頁的內容會隨著捲動不斷的更新,所以就得使用 Selenium 模擬真人操作,在每次更新時抓取內容,透過這個範例,就不用自己手動一張張下載圖片,可全部交由爬蟲處理囉。
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~