批次下载 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 模拟真人操作,在每次更新时抓取内容,透过这个范例,就不用自己手动一张张下载图片,可全部交由爬虫处理啰。
微信扫码关注
抖音扫码关注