Python异步加载怎么爬取图片

发布时间:2021-11-25 09:13:51 作者:iii
来源:亿速云 阅读:291
# 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")

3.2 方案二:逆向API接口

适用于通过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))  # 去重

3.3 方案三:Playwright高级控制

新一代浏览器自动化工具,比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()

四、关键问题解决方案

4.1 处理动态参数

部分网站使用加密参数保护API:

# 示例:解析加密参数
import hashlib

def generate_signature(params):
    secret = 'website_secret_key'
    raw = f"{params}{secret}".encode()
    return hashlib.md5(raw).hexdigest()

4.2 绕过反爬机制

4.3 存储优化

# 使用异步存储提高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())

五、性能优化建议

  1. 并发控制:使用asyncio+aiohttp实现异步请求 “`python import asyncio from aiohttp import ClientSession

async 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字,实际字数可能因代码格式略有差异)

推荐阅读:
  1. python爬取贴吧图片并下载
  2. python如何爬取图片

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

python

上一篇:JDK 1.4 pitfalls 2怎样使用偏好设置并替换properties设置

下一篇:.asmx处理程序提供的功能怎样自动生成WSDL

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》