Python新手写的壁纸爬虫能运行但速度很慢,如何优化?

我知道命名很烂,轻喷,全靠字典直译的! 弄了两个小时才弄出来个 gist 链接,第一次用,凑合看吧

https://gist.github.com/snake1080/817242ef0c0828d7eb3c20692ec2b2c1


Python新手写的壁纸爬虫能运行但速度很慢,如何优化?
18 回复

多线程并发


你这个爬虫慢,八成是网络请求和同步下载的锅。我直接给你个用 aiohttpasyncio 改的异步版本,速度能快一个数量级。

import aiohttp
import asyncio
import os
from urllib.parse import urljoin

async def download_image(session, url, save_path):
    """异步下载单张图片"""
    try:
        async with session.get(url) as response:
            if response.status == 200:
                content = await response.read()
                with open(save_path, 'wb') as f:
                    f.write(content)
                print(f"下载成功: {save_path}")
            else:
                print(f"下载失败,状态码: {response.status}")
    except Exception as e:
        print(f"下载出错 {url}: {e}")

async def main(base_url, page_count, save_dir):
    """主异步函数"""
    os.makedirs(save_dir, exist_ok=True)
    
    # 创建异步会话,设置连接池限制避免被封
    connector = aiohttp.TCPConnector(limit=10)
    async with aiohttp.ClientSession(connector=connector) as session:
        tasks = []
        
        for page in range(1, page_count + 1):
            # 这里替换成你实际的页面URL构造逻辑
            page_url = f"{base_url}/page/{page}"
            
            try:
                async with session.get(page_url) as response:
                    if response.status == 200:
                        html = await response.text()
                        # 这里替换成你实际的图片链接提取逻辑
                        # 示例:假设从HTML中提取了图片链接列表
                        image_urls = extract_image_urls(html)
                        
                        for i, img_url in enumerate(image_urls):
                            # 构造完整URL
                            full_url = urljoin(base_url, img_url)
                            # 生成保存路径
                            filename = f"page{page}_img{i}.jpg"
                            save_path = os.path.join(save_dir, filename)
                            
                            # 创建下载任务
                            task = asyncio.create_task(
                                download_image(session, full_url, save_path)
                            )
                            tasks.append(task)
                    else:
                        print(f"页面请求失败: {page_url}")
            except Exception as e:
                print(f"页面处理出错 {page_url}: {e}")
        
        # 并发执行所有下载任务
        await asyncio.gather(*tasks)

def extract_image_urls(html):
    """从HTML中提取图片链接(需要根据实际网站结构调整)"""
    # 这里只是个示例,你需要用BeautifulSoup或正则表达式替换这部分
    # 示例:假设图片链接在<img src="...">标签中
    import re
    return re.findall(r'<img[^>]+src="([^">]+)"', html)

if __name__ == "__main__":
    # 配置参数
    BASE_URL = "https://example.com/wallpapers"  # 替换成目标网站
    PAGE_COUNT = 5  # 要爬取的页数
    SAVE_DIR = "./wallpapers"  # 保存目录
    
    # 运行异步主函数
    asyncio.run(main(BASE_URL, PAGE_COUNT, SAVE_DIR))

核心改动:

  1. 异步请求:用 aiohttp 替换 requests,网络IO不再阻塞。
  2. 连接池TCPConnector(limit=10) 控制并发连接数,既提速又防封IP。
  3. 任务并发asyncio.gather 同时发起多个下载任务。

你需要改的地方:

  • BASE_URL:换成目标网站。
  • extract_image_urls 函数:用你的解析逻辑(比如 BeautifulSoup)替换我的简单正则。
  • 页面URL构造逻辑(page_url)和图片URL处理逻辑。

一句话总结:换异步IO,速度直接起飞。

感觉慢?? debug 下不就知道哪慢了吗

因为发请求的时候没有并发,每一个图片在下载的时候必须要等待上一个图片的下载流程结束

楼主代码太乱了

IO 密集型用多线程




刚接触 python 两三个月,什么是多线程并发?

哈哈哈哈哈,简单看了一下,你的脚本是下完一张图片后才开始下第二张,能不慢么,去看看多线程吧,让他同时多个照片下载

正在搜索什么是 多线程 哈哈

有什么好问的,去补基础

小白多进城 即可

用多线程,顺便再安利一波我的 https://github.com/cwjokaka/bilibili_member_crawler 里面也用了多线程

https://github.com/piglei/one-python-craftsman 再介绍一个别人(大佬)的项目,是关于编码习惯和 python 技巧的。内容很少但很精炼,我也是看完才动手写项目的

2333…一路循环...我看到了我第一次写爬虫时候的风格

只要不怕 IP 被拉黑
多线程 多进程 并发

多谢 正在找多进程的基础教程看

去看看 asyncio 和 asynchttp

刚在我公众号上推了篇文章,讲怎么改你这个代码的,可以看看: https://mp.weixin.qq.com/s/ZDsoEVY0T2GI9E34dkfUZw

回到顶部