# Python異步加載怎么爬取圖片
## 引言
在當今的Web開發中,異步加載(Asynchronous Loading)已成為提升用戶體驗的主流技術。對于爬蟲開發者而言,這卻帶來了新的挑戰——傳統的同步請求無法直接獲取異步加載的內容(如圖片懶加載、動態渲染等)。本文將詳細介紹如何用Python突破異步加載限制,高效爬取網頁圖片。
---
## 一、理解異步加載機制
### 1.1 什么是異步加載?
異步加載指網頁通過JavaScript動態請求數據并更新DOM,無需刷新整個頁面。常見場景包括:
- 圖片懶加載(Lazy Load):滾動到視口才加載圖片
- 無限滾動(Infinite Scroll):滾動到底部加載新內容
- AJAX動態請求:點擊按鈕后加載數據
### 1.2 識別異步圖片
打開瀏覽器開發者工具(F12):
- **Network面板**:過濾`Img`類型,觀察圖片請求觸發時機
- **XHR/Fetch請求**:部分圖片通過API接口返回
- **滾動測試**:向下滾動時是否出現新圖片請求
---
## 二、技術方案對比
| 方案 | 優點 | 缺點 |
|---------------------|-------------------------|-------------------------------|
| 1. 直接解析HTML | 簡單快速 | 無法獲取異步內容 |
| 2. 模擬瀏覽器 | 可執行JS | 資源消耗大 |
| 3. 分析API接口 | 高效直接 | 需要逆向工程 |
| 4. 混合方案 | 兼顧效率與完整性 | 實現復雜度較高 |
---
## 三、實戰代碼演示
### 3.1 方案一:Selenium模擬瀏覽器
適用于需要完整渲染頁面的場景
```python
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import requests
import os
def download_image(url, filename):
response = requests.get(url, stream=True)
with open(filename, 'wb') as f:
for chunk in response.iter_content(1024):
f.write(chunk)
def crawl_with_selenium(url, save_dir):
# 初始化瀏覽器
options = webdriver.ChromeOptions()
options.add_argument('--headless') # 無頭模式
driver = webdriver.Chrome(options=options)
try:
driver.get(url)
# 模擬滾動觸發懶加載
last_height = driver.execute_script("return document.body.scrollHeight")
while True:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(2) # 等待加載
new_height = driver.execute_script("return document.body.scrollHeight")
if new_height == last_height:
break
last_height = new_height
# 提取圖片
images = driver.find_elements(By.TAG_NAME, 'img')
os.makedirs(save_dir, exist_ok=True)
for idx, img in enumerate(images):
src = img.get_attribute('src')
if src and 'http' in src:
download_image(src, f"{save_dir}/image_{idx}.jpg")
finally:
driver.quit()
# 示例使用
crawl_with_selenium("https://example.com/lazy-load", "downloaded_images")
適用于通過XHR請求獲取數據的網站
import requests
import json
import re
def extract_image_urls(api_url):
headers = {
'User-Agent': 'Mozilla/5.0',
'X-Requested-With': 'XMLHttpRequest'
}
response = requests.get(api_url, headers=headers)
data = response.json()
# 使用正則從JSON中提取圖片URL(根據實際API結構調整)
urls = []
json_str = json.dumps(data)
pattern = r'https?://[^"\s]+?\.(jpg|png|webp)'
urls = re.findall(pattern, json_str, re.I)
return list(set(urls)) # 去重
新一代瀏覽器自動化工具,比Selenium更高效
from playwright.sync_api import sync_playwright
def crawl_with_playwright(url):
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto(url)
# 等待特定元素出現
page.wait_for_selector('img.lazy-loaded')
# 獲取所有圖片元素
images = page.query_selector_all('img')
for img in images:
src = img.get_attribute('src')
print(f"Found image: {src}")
browser.close()
部分網站使用加密參數保護API:
# 示例:解析加密參數
import hashlib
def generate_signature(params):
secret = 'website_secret_key'
raw = f"{params}{secret}".encode()
return hashlib.md5(raw).hexdigest()
fake_useragent
庫# 使用異步存儲提高IO效率
import aiohttp
import aiofiles
async def async_download(url, path):
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
async with aiofiles.open(path, 'wb') as f:
await f.write(await resp.read())
asyncio
+aiohttp
實現異步請求
“`python
import asyncio
from aiohttp import ClientSessionasync def fetch_all(urls): async with ClientSession() as session: tasks = [] for url in urls: task = asyncio.create_task(fetch(url, session)) tasks.append(task) return await asyncio.gather(*tasks)
2. **緩存機制**:對已下載圖片建立MD5校驗
3. **斷點續傳**:記錄已成功下載的URL列表
---
## 結語
爬取異步加載圖片需要根據目標網站的具體實現選擇合適方案。對于簡單懶加載,Selenium/Playwright即可解決;對于復雜API接口,需要結合網絡抓包和逆向分析。隨著Web技術的演進,爬蟲開發者需要持續學習新的反爬對策和技術方案。
> **注意事項**:爬取前務必檢查網站的`robots.txt`文件,遵守版權法規和相關服務條款。
(全文約1680字,實際字數可能因代碼格式略有差異)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。