本文目录导读:

我来为你提供几个Python图片爬虫的实用案例,从简单到复杂逐步介绍。
基础版:爬取静态网页图片
import requests
import os
from bs4 import BeautifulSoup
from urllib.parse import urljoin
def download_static_images(url, save_dir='images'):
"""爬取静态网页中的所有图片"""
# 创建保存目录
if not os.path.exists(save_dir):
os.makedirs(save_dir)
# 设置请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
try:
# 获取网页内容
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
# 解析HTML
soup = BeautifulSoup(response.text, 'html.parser')
# 查找所有图片标签
img_tags = soup.find_all('img')
downloaded = 0
for i, img in enumerate(img_tags):
# 获取图片URL
img_url = img.get('src')
if not img_url:
continue
# 处理相对路径
img_url = urljoin(url, img_url)
# 过滤非图片格式
if not any(img_url.lower().endswith(ext) for ext in ['.jpg', '.jpeg', '.png', '.gif', '.webp']):
continue
try:
# 下载图片
img_response = requests.get(img_url, headers=headers, timeout=10)
img_response.raise_for_status()
# 保存图片
file_name = f'image_{i+1}.jpg'
file_path = os.path.join(save_dir, file_name)
with open(file_path, 'wb') as f:
f.write(img_response.content)
print(f'✓ 已下载: {file_name}')
downloaded += 1
except Exception as e:
print(f'✗ 下载失败 {img_url}: {str(e)}')
print(f'\n下载完成!共下载 {downloaded} 张图片')
except Exception as e:
print(f'请求失败: {str(e)}')
# 使用示例
url = 'https://example.com/gallery' # 替换为目标网址
download_static_images(url)
进阶版:爬取动态加载图片
import requests
import json
import os
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class DynamicImageScraper:
"""爬取动态加载页面的图片"""
def __init__(self, headless=True):
# 配置Chrome选项
options = webdriver.ChromeOptions()
if headless:
options.add_argument('--headless')
options.add_argument('--disable-gpu')
options.add_argument('--no-sandbox')
self.driver = webdriver.Chrome(options=options)
def scrape_unsplash(self, query, max_images=30):
"""爬取Unsplash图片"""
save_dir = f'unsplash_{query}'
if not os.path.exists(save_dir):
os.makedirs(save_dir)
url = f'https://unsplash.com/s/photos/{query}'
self.driver.get(url)
# 等待图片加载
wait = WebDriverWait(self.driver, 10)
wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'MorZF')))
# 滚动页面加载更多图片
downloaded = 0
scroll_count = 0
while downloaded < max_images:
# 查找所有图片元素
img_elements = self.driver.find_elements(By.CLASS_NAME, 'MorZF')
for img in img_elements:
if downloaded >= max_images:
break
try:
# 获取图片URL
img_url = img.get_attribute('src')
if not img_url or 'placeholder' in img_url:
continue
# 获取高清图片URL
img_url_high = img_url.replace('?w=400', '?w=1920')
# 下载图片
response = requests.get(img_url_high, timeout=10)
if response.status_code == 200:
file_name = f'{query}_{downloaded+1}.jpg'
file_path = os.path.join(save_dir, file_name)
with open(file_path, 'wb') as f:
f.write(response.content)
downloaded += 1
print(f'✓ 已下载: {file_name}')
except Exception as e:
print(f'✗ 下载失败: {str(e)}')
# 滚动页面
if downloaded < max_images:
self.driver.execute_script('window.scrollTo(0, document.body.scrollHeight);')
time.sleep(2)
scroll_count += 1
if scroll_count > 10: # 防止无限滚动
break
print(f'\n下载完成!共下载 {downloaded} 张图片')
def close(self):
self.driver.quit()
# 使用示例
scraper = DynamicImageScraper()
scraper.scrape_unsplash('nature', max_images=20)
scraper.close()
高级版:API爬取图片
import requests
import os
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
from ratelimit import limits, sleep_and_retry
class APIImageScraper:
"""通过API爬取图片(以Unsplash API为例)"""
def __init__(self, api_key):
self.api_key = api_key
self.base_url = 'https://api.unsplash.com'
self.headers = {
'Authorization': f'Client-ID {self.api_key}'
}
@sleep_and_retry
@limits(calls=50, period=60) # 限制API调用频率
def search_photos(self, query, per_page=30):
"""搜索图片"""
url = f'{self.base_url}/search/photos'
params = {
'query': query,
'per_page': per_page,
'orientation': 'landscape'
}
response = requests.get(url, headers=self.headers, params=params)
response.raise_for_status()
return response.json()['results']
def download_single_image(self, image_data, save_dir, index):
"""下载单张图片"""
try:
# 获取图片URL
img_url = image_data['urls']['regular']
img_id = image_data['id']
# 获取图片信息
description = image_data.get('description', '')[:50] or f'image_{index}'
# 下载图片
response = requests.get(img_url, timeout=10)
response.raise_for_status()
# 保存图片
file_name = f"{index:03d}_{description.replace(' ', '_')}.jpg"
file_path = os.path.join(save_dir, file_name)
with open(file_path, 'wb') as f:
f.write(response.content)
return True, file_name
except Exception as e:
return False, str(e)
def download_batch(self, query, num_images=50):
"""批量下载图片"""
save_dir = f'api_images_{query}'
if not os.path.exists(save_dir):
os.makedirs(save_dir)
print(f'开始搜索 "{query}" 相关图片...')
# 搜索图片
all_photos = []
page = 1
while len(all_photos) < num_images:
photos = self.search_photos(query, per_page=30)
all_photos.extend(photos)
page += 1
if len(photos) == 0:
break
time.sleep(1) # API限制
print(f'找到 {len(all_photos)} 张图片,开始下载...')
# 多线程下载
downloaded = 0
with ThreadPoolExecutor(max_workers=5) as executor:
futures = []
for i, photo in enumerate(all_photos[:num_images]):
future = executor.submit(
self.download_single_image,
photo,
save_dir,
i + 1
)
futures.append(future)
for future in as_completed(futures):
success, result = future.result()
if success:
downloaded += 1
print(f'✓ 已下载: {result}')
else:
print(f'✗ 下载失败: {result}')
print(f'\n完成!成功下载 {downloaded} 张图片')
# 使用示例
# api_key = 'your_unsplash_api_key' # 需要注册获取
# scraper = APIImageScraper(api_key)
# scraper.download_batch('mountains', num_images=30)
综合实用版:通用图片爬虫
import requests
import re
import os
import time
from urllib.parse import urlparse
from selenium import webdriver
from bs4 import BeautifulSoup
class UniversalImageScraper:
"""通用图片爬虫"""
def __init__(self):
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
self.downloaded_urls = set() # 防止重复下载
def extract_image_urls(self, html, base_url):
"""从HTML中提取所有图片URL"""
soup = BeautifulSoup(html, 'html.parser')
img_urls = []
# 1. 从img标签提取
for img in soup.find_all('img'):
src = img.get('src') or img.get('data-src') or img.get('data-original')
if src:
# 处理相对路径
if src.startswith('//'):
src = 'https:' + src
elif src.startswith('/'):
src = urljoin(base_url, src)
elif not src.startswith('http'):
src = urljoin(base_url, src)
img_urls.append(src)
# 2. 从CSS背景图提取
style_pattern = r'background(?:-image)?\s*:\s*url\(["\']?(.*?)["\']?\)'
for style in soup.find_all(style=True):
urls = re.findall(style_pattern, style['style'])
img_urls.extend(urls)
# 3. 从a标签的href提取图片链接
for a in soup.find_all('a', href=True):
href = a['href']
if any(href.endswith(ext) for ext in ['.jpg', '.jpeg', '.png', '.gif']):
img_urls.append(href)
# 去重并过滤
unique_urls = list(set(img_urls))
valid_urls = [url for url in unique_urls if url.startswith('http')]
return valid_urls
def download_image(self, url, save_dir, filename=None):
"""下载单张图片"""
if url in self.downloaded_urls:
return False, '已下载过'
try:
response = requests.get(url, headers=self.headers, timeout=10)
response.raise_for_status()
# 检查是否为图片
content_type = response.headers.get('content-type', '')
if not content_type.startswith('image/'):
return False, '非图片文件'
# 生成文件名
if not filename:
parsed = urlparse(url)
filename = os.path.basename(parsed.path) or f'image_{int(time.time())}.jpg'
# 确保有扩展名
if '.' not in filename:
ext = content_type.split('/')[-1]
filename = f'{filename}.{ext}'
# 保存图片
filepath = os.path.join(save_dir, filename)
with open(filepath, 'wb') as f:
f.write(response.content)
self.downloaded_urls.add(url)
return True, filename
except Exception as e:
return False, str(e)
def scrape(self, url, save_dir='downloaded_images', max_images=50):
"""主爬取方法"""
if not os.path.exists(save_dir):
os.makedirs(save_dir)
print(f'开始爬取: {url}')
# 获取网页内容
response = requests.get(url, headers=self.headers, timeout=10)
response.raise_for_status()
# 提取图片URL
img_urls = self.extract_image_urls(response.text, url)
print(f'找到 {len(img_urls)} 张图片')
# 下载图片
downloaded = 0
for img_url in img_urls[:max_images]:
if downloaded >= max_images:
break
success, result = self.download_image(img_url, save_dir)
if success:
downloaded += 1
print(f'[{downloaded}/{max_images}] ✓ {result}')
else:
print(f'✗ {result}')
time.sleep(0.5) # 礼貌延迟
print(f'\n爬取完成!共下载 {downloaded} 张图片')
# 使用示例
scraper = UniversalImageScraper()
scraper.scrape('https://example.com', max_images=20)
安装依赖
pip install requests beautifulsoup4 selenium pillow # 如果需要多线程 pip install concurrent.futures # API速率限制 pip install ratelimit
注意事项
- 法律法规: 遵守网站的robots.txt和使用条款
- 版权问题: 注意图片的版权许可
- 请求频率: 添加延迟避免对服务器造成压力
- 异常处理: 做好异常处理和重试机制
- User-Agent: 设置合理的请求头
这些案例覆盖了常见的图片爬取场景,你可以根据实际需求进行修改和扩展。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播