从零构建自动化流程:Python爬虫收集素材驱动Qwen-Image-Edit-F2P创作

1. 引言

你有没有遇到过这样的困境?脑子里有个绝妙的创意,想用AI图像编辑工具把它变成现实,比如给一张人物照片换个背景、换个发型,或者尝试一种全新的艺术风格。但第一步就卡住了——找不到合适的高质量参考图片。去图库网站一张张手动搜索、下载、整理,这个过程既枯燥又耗时,灵感可能就在这个过程中消磨殆尽了。

对于设计师、内容创作者或者任何需要批量处理图像创意的人来说,这种“找素材”的痛点尤为明显。如果能把“找素材”和“生成创意”这两个环节打通,形成一个自动化的流水线,那该多好?想象一下,设定好你想要的主题或风格关键词,程序就能自动去网上寻找相关的图片或描述,然后直接丢给AI图像模型去生成新的创意作品,整个过程完全不需要你手动干预。

今天,我们就来把这个想法变成现实。我将带你一步步搭建一个端到端的自动化内容创作流水线。这个系统的核心思路很简单:用Python爬虫作为我们的“眼睛”和“手”,去互联网上合法地收集灵感素材;然后,让这些素材自动“喂”给强大的Qwen-Image-Edit-F2P模型,驱动它进行批量化的创意生成;最后,所有生成的作品会被自动整理归档,等着你来检阅。

整个过程就像设置了一个全自动的“灵感探索与素材生产车间”。你只需要提供初始的“种子”想法,剩下的脏活累活,都交给代码来完成。这不仅极大地提升了效率,更重要的是,它开启了一种全新的、数据驱动的创意工作流。下面,我们就从零开始,把这个车间搭建起来。

2. 整体方案设计:我们的自动化创意流水线

在动手写代码之前,我们先来俯瞰一下整个系统的蓝图。理解了这个流程,后面的每一步操作就会变得清晰明了。

我们的自动化流水线主要包含三个核心环节,它们像流水线上的三个工位,紧密协作:

  1. 素材采集工位(Python爬虫):这是流水线的起点。它的任务是根据我们设定的关键词(比如“都市夜景”、“复古肖像画风”),自动访问那些允许爬取的公开艺术图库或素材网站。它会模拟人的浏览行为,找到相关的图片,并把它们的下载链接、甚至是图片本身的风格描述文本“抓”下来。这里的关键是“合法”与“精准”,我们只获取公开可用的信息,并且要确保抓取到的素材确实符合我们的创意方向。

  2. 创意生成工位(Qwen-Image-Edit-F2P + ComfyUI API):这是流水线的核心加工车间。爬虫收集来的素材(图片URL或文本描述)会被送到这里。我们会通过ComfyUI提供的API接口,来远程指挥Qwen-Image-Edit-F2P这个AI画师。你可以这样理解:爬虫递过来一张“参考图”和一段“修改要求”(比如“把背景换成雪山”),API就像是一个传令官,把这个任务准确地传达给AI画师。画师接到指令后,就开始工作,生成一张新的、符合要求的图片。

  3. 成品归档工位(本地文件系统):这是流水线的终点。AI画师生成好的图片,不能乱放。我们需要一个自动化的归档系统。根据图片的生成参数、主题或日期,程序会自动创建文件夹,把生成的作品分门别类地保存好。这样,当你结束一天的工作,打开归档目录,所有新鲜出炉的创意作品都整齐地摆在那里,随时可以取用。

整个流程的驱动核心是一个Python主控脚本。它负责调度这三个环节:先启动爬虫,等爬虫把素材收集到一个列表里,然后遍历这个列表,一次一个地把素材发送给AI生成工位,最后把生成的结果送到归档工位。这个过程可以设定为循环执行,实现7x24小时不间断的灵感探索。

为了让这个蓝图更直观,我们可以看看下面这个简单的流程图,它描绘了数据是如何在这三个模块间流动的:

[用户输入关键词] 
    → 
[Python主控脚本] 
    → 
[爬虫模块:采集图片/文本素材] 
    → 
[素材清洗与格式化] 
    → 
[调用ComfyUI API,驱动Qwen-Image-Edit-F2P生成] 
    → 
[结果图片自动保存到本地目录]

接下来,我们就进入实战环节,从第一个工位——爬虫开始搭建。

3. 第一步:构建智能素材爬虫(Python实现)

我们的爬虫目标是成为一个高效的“素材侦察兵”。为了兼顾教学的通用性和合法性,我们选择以一个允许爬虫、资源丰富的公开艺术图库为例(在实际应用中,请务必严格遵守目标网站的robots.txt协议和服务条款)。我们假设需要收集“油画肖像”风格的人脸参考图。

这个爬虫不仅要能下载图片,最好还能提取一些相关的文本信息(如标签、标题),这些信息后续可以作为生成AI图像的提示词补充。我们会使用requests库来获取网页,用BeautifulSoup库来解析和提取数据,并用os库来管理文件。

import requests
from bs4 import BeautifulSoup
import os
import time
import re

class ArtImageCrawler:
    def __init__(self, keyword, save_dir='./crawled_images', max_images=10):
        """
        初始化爬虫
        :param keyword: 搜索关键词,如 'oil painting portrait'
        :param save_dir: 图片保存目录
        :param max_images: 最大下载图片数量
        """
        self.keyword = keyword.replace(' ', '+')  # 处理搜索词中的空格
        self.save_dir = save_dir
        self.max_images = max_images
        self.image_urls = []  # 存储找到的图片链接
        self.image_info = []  # 存储图片的附加信息(如标题、风格)
        
        # 创建保存目录
        if not os.path.exists(save_dir):
            os.makedirs(save_dir)
            
        # 设置请求头,模拟浏览器访问
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
        }
    
    def search_and_parse(self, base_url):
        """
        模拟搜索并解析结果页面,提取图片链接和信息。
        注意:这是一个示例函数,实际URL和解析规则需根据目标网站调整。
        """
        # 构造搜索URL(此处为示例,需替换为真实网站搜索模式)
        search_url = f"{base_url}/search?q={self.keyword}"
        print(f"正在搜索: {search_url}")
        
        try:
            response = requests.get(search_url, headers=self.headers, timeout=10)
            response.raise_for_status()  # 检查请求是否成功
            soup = BeautifulSoup(response.text, 'html.parser')
            
            # 示例:假设图片链接在带有'img-item'类的div中的img标签的‘data-src’属性里
            # 实际解析规则需要你通过查看目标网页的HTML结构来确定
            img_elements = soup.find_all('img', {'class': 'artwork-image'})  # 请替换为实际的类名或选择器
            
            for img in img_elements[:self.max_images]:
                # 优先获取高分辨率图片的链接属性,可能是‘src’, ‘data-src’, ‘data-original’等
                img_url = img.get('data-src') or img.get('src') 
                if img_url and img_url.startswith('http'):
                    # 补全可能省略的域名
                    if img_url.startswith('//'):
                        img_url = 'https:' + img_url
                    elif img_url.startswith('/'):
                        img_url = base_url + img_url
                    
                    # 提取图片的alt文本作为描述信息
                    alt_text = img.get('alt', '')
                    # 简单地从alt文本或周围元素中提取风格关键词(示例)
                    style_keywords = self._extract_style_from_text(alt_text)
                    
                    self.image_urls.append(img_url)
                    self.image_info.append({
                        'url': img_url,
                        'alt': alt_text,
                        'style_keywords': style_keywords,
                        'source_page': search_url
                    })
                    print(f"  找到图片: {alt_text[:50]}...")
            
            print(f"搜索完成,共找到 {len(self.image_urls)} 张潜在图片。")
            
        except requests.RequestException as e:
            print(f"网络请求出错: {e}")
        except Exception as e:
            print(f"解析页面时出错: {e}")
    
    def _extract_style_from_text(self, text):
        """一个简单的函数,用于从文本中提取可能的美术风格关键词。"""
        styles = ['oil painting', 'watercolor', 'sketch', 'digital art', 'impressionism', 'realism', 'abstract']
        found_styles = []
        for style in styles:
            if style in text.lower():
                found_styles.append(style)
        return found_styles if found_styles else ['general portrait']
    
    def download_images(self):
        """下载收集到的图片到本地。"""
        print(f"开始下载图片到目录: {self.save_dir}")
        downloaded_count = 0
        
        for i, info in enumerate(self.image_info):
            img_url = info['url']
            try:
                # 获取图片二进制数据
                img_data = requests.get(img_url, headers=self.headers, timeout=15).content
                # 生成文件名:关键词_序号_风格关键词
                style_suffix = '_'.join(info['style_keywords'][:2]) if info['style_keywords'] else 'unknown'
                safe_style = re.sub(r'[\\/*?:"<>|]', "_", style_suffix)  # 清理文件名中的非法字符
                file_name = f"{self.keyword.replace('+', '_')}_{i}_{safe_style}.jpg"
                file_path = os.path.join(self.save_dir, file_name)
                
                # 保存图片
                with open(file_path, 'wb') as f:
                    f.write(img_data)
                
                # 同时保存一个文本文件,记录图片的元信息,后续可作为AI提示词
                meta_file_path = file_path.replace('.jpg', '.txt')
                with open(meta_file_path, 'w', encoding='utf-8') as f:
                    f.write(f"Source URL: {info['url']}\n")
                    f.write(f"Alt Text: {info['alt']}\n")
                    f.write(f"Inferred Style: {', '.join(info['style_keywords'])}\n")
                
                downloaded_count += 1
                print(f"  已下载 ({downloaded_count}/{len(self.image_urls)}): {file_name}")
                time.sleep(1)  # 礼貌性延迟,避免对服务器造成压力
                
            except Exception as e:
                print(f"  下载失败 {img_url}: {e}")
        
        print(f"下载完成。成功下载 {downloaded_count} 张图片。")
        return downloaded_count

# 使用示例
if __name__ == '__main__':
    # 注意:请将 `https://example-art-site.com` 替换为真实的、允许爬虫的网站地址
    crawler = ArtImageCrawler(keyword='oil painting portrait', max_images=5)
    crawler.search_and_parse(base_url='https://example-art-site.com')  # 请使用合法目标网站
    crawler.download_images()

代码要点解析:

  • 合法性第一:代码中包含了模拟浏览器的请求头(User-Agent)和请求延迟(time.sleep),这是尊重网站服务器、避免被封IP的基本礼仪。在实际使用前,务必检查目标网站的robots.txt文件和服务条款。
  • 健壮性:代码使用了try...except块来处理网络请求和文件操作中可能出现的错误,确保程序不会因为一张图片下载失败而完全崩溃。
  • 信息丰富:我们不仅下载图片,还保存了与之相关的文本信息(alt文本和提取的风格关键词)。这些文本信息在下一步中会变得非常有用,它们可以作为给AI模型的“灵感提示”,告诉它我们想要的大致风格。
  • 可扩展性search_and_parse_extract_style_from_text函数是示例性的。你需要根据具体目标网站的实际HTML结构来调整图片链接和信息的提取规则。这可能需要你使用浏览器的“开发者工具”来查看网页源码。

运行这段代码后,你的./crawled_images目录下应该会出现一批“油画肖像”图片以及对应的文本描述文件。我们的素材库已经初步建成了。

4. 第二步:连接AI画师(ComfyUI API调用详解)

有了素材,下一步就是请出我们的“AI画师”——Qwen-Image-Edit-F2P。我们通过ComfyUI来调用它。ComfyUI是一个基于节点流程的AI图像生成工具,它提供了强大的API,允许我们通过发送一个定义了工作流(workflow)的JSON数据,来远程执行生成任务。

首先,你需要确保已经部署了包含Qwen-Image-Edit-F2P模型的ComfyUI服务,并且API服务是开启的(通常运行ComfyUI时会有一个--listen参数来开启网络访问)。

我们的目标是构建一个API请求,这个请求里包含了我们要编辑的图片(来自爬虫)、编辑指令(比如“换成星空背景”),以及其他生成参数(尺寸、步数等)。

import json
import requests
import base64
from io import BytesIO
from PIL import Image

class ComfyUI_Client:
    def __init__(self, server_address="127.0.0.1:8188"):
        """
        初始化ComfyUI API客户端
        :param server_address: ComfyUI服务器地址,例如 "127.0.0.1:8188" 或 "你的服务器IP:端口"
        """
        self.server_address = server_address
        self.base_url = f"http://{server_address}"
        self.client_id = "your_client_id_here"  # 可选,用于标识客户端
        
    def _load_workflow_template(self):
        """
        加载一个预定义的Qwen-Image-Edit-F2P工作流模板。
        这个JSON结构定义了ComfyUI中各个节点的连接和参数。
        你需要先在ComfyUI界面中手动搭建并测试好一个可用的工作流,然后将其导出为API格式。
        """
        # 这是一个高度简化的示例模板,实际工作流JSON会复杂得多。
        # 关键节点通常包括:LoadImage(加载图片),QwenImageEditF2P(编辑模型),VAEDecode(解码),SaveImage(保存)。
        workflow_template = {
            "3": {
                "class_type": "LoadImage",
                "inputs": {
                    "image": "example_image.jpg"  # 这个值会被动态替换
                }
            },
            "6": {
                "class_type": "QwenImageEditF2P",  # 节点类型,根据实际名称调整
                "inputs": {
                    "image": ["3", 0],  # 连接到LoadImage节点的输出
                    "prompt": "a portrait in the style of van gogh",  # 编辑提示词,会被动态替换
                    "negative_prompt": "",  # 负面提示词
                    "steps": 20,
                    "cfg_scale": 7.5,
                    # ... 其他模型参数
                }
            },
            "9": {
                "class_type": "SaveImage",
                "inputs": {
                    "images": ["6", 0],  # 连接到QwenImageEditF2P节点的输出
                    "filename_prefix": "ComfyUI"  # 文件名前缀,可动态替换
                }
            }
        }
        return workflow_template
    
    def _encode_image_to_base64(self, image_path):
        """将本地图片文件编码为Base64字符串,用于API传输。"""
        try:
            with open(image_path, "rb") as image_file:
                encoded_string = base64.b64encode(image_file.read()).decode('utf-8')
            # ComfyUI的LoadImage节点可能需要一个特定的格式,有时需要上传文件而不是base64。
            # 更常见的做法是通过单独的upload接口上传图片,获得一个文件名,然后在workflow中引用该文件名。
            # 这里为了简化,展示base64方式。实际使用请参考ComfyUI的API文档。
            return encoded_string
        except Exception as e:
            print(f"编码图片失败 {image_path}: {e}")
            return None
    
    def generate_with_image_and_prompt(self, image_path, prompt, output_prefix="edited"):
        """
        核心函数:给定图片路径和提示词,驱动AI生成新图片。
        :param image_path: 本地待编辑图片的路径
        :param prompt: 编辑指令,例如 "change the background to a starry night sky"
        :param output_prefix: 输出图片的文件名前缀
        :return: 生成图片的保存路径列表(通常ComfyUI会保存到其output目录)
        """
        # 1. 上传图片(推荐方式)
        upload_url = f"{self.base_url}/upload/image"
        try:
            with open(image_path, 'rb') as f:
                files = {'image': f}
                response = requests.post(upload_url, files=files)
                upload_result = response.json()
                # 假设返回结果中包含服务器上的文件名
                server_image_filename = upload_result.get('name')
                if not server_image_filename:
                    print("上传图片失败,未能获取服务器文件名。")
                    return None
        except Exception as e:
            print(f"上传图片失败: {e}")
            # 如果上传失败,可以尝试回退到在workflow中直接使用本地路径(需确保ComfyUI能访问到)
            server_image_filename = image_path  # 注意:这要求ComfyUI服务与脚本在同一机器或能访问共享存储
        
        # 2. 准备工作流数据
        workflow = self._load_workflow_template()
        # 动态修改工作流中的关键参数
        # 修改LoadImage节点加载的图片名
        workflow["3"]["inputs"]["image"] = server_image_filename
        # 修改QwenImageEditF2P节点的提示词
        workflow["6"]["inputs"]["prompt"] = prompt
        # 修改SaveImage节点的输出前缀
        workflow["9"]["inputs"]["filename_prefix"] = output_prefix
        
        # 3. 将工作流数据排队
        queue_url = f"{self.base_url}/prompt"
        prompt_payload = {
            "prompt": workflow,
            "client_id": self.client_id
        }
        
        try:
            response = requests.post(queue_url, json=prompt_payload)
            response_json = response.json()
            prompt_id = response_json.get('prompt_id')
            if prompt_id:
                print(f"生成任务已提交,Prompt ID: {prompt_id}")
                # 这里可以添加轮询逻辑,检查任务是否完成并获取结果图片
                # 一个简单的方法是等待一段时间,然后去ComfyUI的输出目录查看最新文件
                return self._wait_and_fetch_result(prompt_id, output_prefix)
            else:
                print("提交任务失败,未收到有效的Prompt ID。")
                return None
        except Exception as e:
            print(f"调用API失败: {e}")
            return None
    
    def _wait_and_fetch_result(self, prompt_id, output_prefix):
        """
        等待任务完成并获取结果。
        这是一个简化示例。实际应用中,你需要通过ComfyUI的history或view API来获取生成结果。
        这里我们假设任务完成后,图片会保存在ComfyUI的默认输出目录,并按照前缀命名。
        """
        import time
        time.sleep(15)  # 简单等待15秒,实际时间取决于模型和参数
        print(f"任务 {prompt_id} 预计已完成,请检查ComfyUI的输出目录。")
        # 更佳实践:调用 /history/{prompt_id} API 获取任务执行详情和输出图片信息
        history_url = f"{self.base_url}/history/{prompt_id}"
        try:
            history_resp = requests.get(history_url)
            history_data = history_resp.json()
            # 从history_data中解析出生成的图片文件名
            # ... 解析逻辑 ...
            # 假设我们解析到了一个文件名列表
            output_filenames = [f"{output_prefix}_00001_.png"]  # 示例
            return output_filenames
        except:
            # 如果获取历史失败,返回提示信息
            return [f"请手动查看输出目录,查找以'{output_prefix}'开头的文件。"]

# 使用示例
if __name__ == '__main__':
    client = ComfyUI_Client("127.0.0.1:8188")
    # 假设我们有一张爬虫下载的图片
    test_image_path = "./crawled_images/oil_painting_portrait_0_oil_painting.jpg"
    test_prompt = "Transform the portrait into a cyberpunk style, with neon lights and rain."
    result = client.generate_with_image_and_prompt(test_image_path, test_prompt, "cyberpunk_portrait")
    print(f"生成结果: {result}")

关键点与注意事项:

  1. 工作流模板是核心_load_workflow_template函数返回的JSON,必须与你本地ComfyUI中搭建并测试成功的那个工作流完全一致。最可靠的方法是:在ComfyUI界面手动搭建好一个能正常工作的流程,然后使用其内置的“保存工作流为API格式”功能(或相关插件),直接将JSON复制到代码中。
  2. 图片上传方式:直接使用Base64编码嵌入工作流可能不适用于所有节点。更通用的做法是先用/upload/image API将图片上传到ComfyUI服务器,获得一个服务器端的文件名,然后在工作流JSON中引用这个文件名。
  3. 异步与轮询/prompt API是异步的,提交后立即返回一个prompt_id。你需要用这个ID去轮询/history接口,才能知道任务是否完成,并获取生成图片的具体信息(如保存在服务器上的路径)。上面的_wait_and_fetch_result函数只是一个简单的示意,生产环境需要更完善的轮询和错误处理逻辑。
  4. 参数调整:工作流中的steps(步数)、cfg_scale(提示词相关性)等参数对生成效果影响很大。你需要在ComfyUI界面中反复调试,找到一组效果稳定的参数,再固化到API调用的模板里。

当这一步调试成功,意味着你已经能够用代码远程控制AI画师进行创作了。接下来,我们把前两步连接起来。

5. 第三步:组装全自动流水线

现在,我们有了能采集素材的“手”(爬虫),也有了能进行创作的“大脑”(AI API客户端)。最后一步,就是编写一个“主控程序”,让它们协同工作,实现从关键词到成品的全自动化。

这个主控程序的工作流程是:

  1. 接收用户输入(例如,一个主题列表)。
  2. 针对每个主题,启动爬虫收集一批参考图片和描述。
  3. 对于收集到的每张图片,结合其元信息(比如自带的风格标签)和用户指令,构造一个给AI的“创作提示词”。
  4. 调用ComfyUI客户端,驱动AI基于该图片和提示词进行创作。
  5. 将AI生成的作品自动保存到按主题、日期等分类的文件夹中。
import os
import shutil
from datetime import datetime
# 假设我们已经有了上面定义的 ArtImageCrawler 和 ComfyUI_Client 类

class AutomatedCreationPipeline:
    def __init__(self, comfyui_server="127.0.0.1:8188"):
        self.crawler = None
        self.comfyui_client = ComfyUI_Client(comfyui_server)
        self.base_output_dir = "./ai_generated_artworks"
        
    def run_pipeline_for_topic(self, search_topic, edit_instruction_template, images_to_process=3):
        """
        为一个搜索主题运行完整的流水线。
        :param search_topic: 搜索关键词,如 "renaissance portrait"
        :param edit_instruction_template: 编辑指令模板,例如 "Convert this into a {style} style painting."
                                        {style} 会被爬虫提取的风格关键词替换。
        :param images_to_process: 从爬取的图片中处理多少张
        """
        print(f"\n{'='*50}")
        print(f"开始处理主题: {search_topic}")
        print(f"{'='*50}")
        
        # 1. 爬取素材
        crawl_save_dir = os.path.join("./crawled_images", search_topic.replace(' ', '_'))
        self.crawler = ArtImageCrawler(keyword=search_topic, save_dir=crawl_save_dir, max_images=images_to_process*2) # 多爬一些以防有无效链接
        # 注意:这里需要替换为真实的、合法的目标网站URL
        self.crawler.search_and_parse(base_url='https://example-art-site.com')
        downloaded_count = self.crawler.download_images()
        
        if downloaded_count == 0:
            print(f"主题 '{search_topic}' 未爬取到图片,跳过。")
            return
        
        # 2. 为每张图片构造提示词并调用AI生成
        today_str = datetime.now().strftime("%Y%m%d")
        topic_output_dir = os.path.join(self.base_output_dir, f"{search_topic.replace(' ', '_')}_{today_str}")
        os.makedirs(topic_output_dir, exist_ok=True)
        
        processed = 0
        for i, img_info in enumerate(self.crawler.image_info[:images_to_process]):
            img_path = os.path.join(crawl_save_dir, f"{search_topic.replace(' ', '_')}_{i}_*.jpg")
            # 上面生成的文件名模式需要匹配,这里简化处理,实际中需要更精确地定位刚下载的文件
            # 一种更稳妥的方式是让download_images函数返回下载成功的文件路径列表
            actual_img_list = [f for f in os.listdir(crawl_save_dir) if f.startswith(f"{search_topic.replace(' ', '_')}_{i}_") and f.endswith('.jpg')]
            if not actual_img_list:
                print(f"  未找到第 {i} 张图片文件,跳过。")
                continue
            actual_img_path = os.path.join(crawl_save_dir, actual_img_list[0])
            
            # 构造个性化的提示词
            style_from_image = img_info['style_keywords']
            # 如果图片自带风格信息,则融入提示词;否则使用通用指令
            if style_from_image and style_from_image[0] != 'general portrait':
                # 例如,如果图片风格是['oil painting'],指令模板是“Convert this into a {style} style painting.”
                # 则最终提示词为:“Convert this into a oil painting style painting.”
                # 你可能想用更自然的方式组合,比如:“Repaint this portrait in the style of {style}.”
                specific_instruction = edit_instruction_template.format(style=style_from_image[0])
            else:
                specific_instruction = edit_instruction_template.format(style="modern digital art")  # 默认风格
            
            # 可以结合图片的alt文本进一步丰富提示词
            alt_snippet = img_info['alt'][:100]  # 取前100个字符
            final_prompt = f"{specific_instruction} Inspired by: {alt_snippet}"
            
            print(f"\n  --- 处理图片 {i+1}/{min(images_to_process, downloaded_count)} ---")
            print(f"  图片: {os.path.basename(actual_img_path)}")
            print(f"  风格关键词: {style_from_image}")
            print(f"  生成指令: {final_prompt}")
            
            # 3. 调用AI生成
            output_prefix = f"{search_topic.replace(' ', '_')}_edit_{i}"
            result = self.comfyui_client.generate_with_image_and_prompt(
                image_path=actual_img_path,
                prompt=final_prompt,
                output_prefix=output_prefix
            )
            
            if result:
                print(f"  生成成功!结果: {result}")
                # 4. (可选)将生成的结果文件从ComfyUI默认目录移动到我们的主题目录
                # 这里需要根据_comfyui_client._wait_and_fetch_result实际返回的路径来操作
                # 例如: shutil.move(result_file_path, topic_output_dir)
                processed += 1
            else:
                print(f"  生成失败。")
            
            # 每次生成后稍作停顿,避免服务器压力过大
            import time
            time.sleep(5)
        
        print(f"\n主题 '{search_topic}' 处理完成。成功生成 {processed} 张新作品,保存在: {topic_output_dir}")

# 运行示例
if __name__ == '__main__':
    pipeline = AutomatedCreationPipeline("127.0.0.1:8188")
    
    # 定义你想要探索的主题和对应的创作指令
    creative_briefs = [
        {
            "topic": "classical sculpture face",
            "instruction": "Reimagine this face as a living character in a {style} fantasy setting."
        },
        {
            "topic": "abstract art texture",
            "instruction": "Use this texture as a base to generate a {style} landscape."
        }
    ]
    
    for brief in creative_briefs:
        pipeline.run_pipeline_for_topic(
            search_topic=brief["topic"],
            edit_instruction_template=brief["instruction"],
            images_to_process=2  # 每个主题处理2张图片
        )
    
    print("\n🎉 所有自动化创作任务已完成!请查看 './ai_generated_artworks' 目录下的作品。")

流水线的精妙之处:

  • 数据驱动创意:提示词不再是完全凭空想象。它结合了爬虫从素材中提取的“风格关键词”({style})和图片自带的描述(alt_snippet),使得AI的创作既有明确的指令,又保留了原始素材的一些“基因”或“灵感”,从而产生更相关、有时更令人惊喜的结果。
  • 批量与自动化:整个for循环实现了批量化处理。你可以一次性输入多个主题,程序就会依次为每个主题执行“爬取->生成”的完整流程,真正实现无人值守。
  • 结构化归档:生成的作品按照主题和日期自动归档,便于后续的管理、筛选和展示。

运行这个主程序,泡一杯咖啡,回来时你就会发现,一个属于你的、小小的自动化创意工厂已经运转完毕,产出了一批融合了网络灵感与AI创造力的独特作品。

6. 总结

回顾我们搭建的这个自动化流程,它本质上是一个将数据获取、智能处理和文件管理串联起来的创意引擎。我们从互联网这个最大的灵感库中自动汲取养分(爬虫),用这些养分来引导和激发一个强大的AI模型(Qwen-Image-Edit-F2P),最后将创意的果实井井有条地保存下来。

这个过程的价值不仅仅在于节省了时间。更重要的是,它改变了我们与创意工具互动的方式。你从一个被动的、手动的操作者,变成了一个策略的制定者和流程的监督者。你的核心工作变成了:定义有趣的搜索主题、构思巧妙的编辑指令模板、然后审视和挑选系统生成的海量结果。这是一种更高效、也更有可能碰撞出意外惊喜的创作模式。

在实际使用中,你还可以对这个流水线进行无数有趣的扩展:比如,让爬虫去抓取社交媒体上的热门视觉趋势,然后自动生成一批符合趋势的营销素材;或者,建立一个自己的“风格种子库”,让AI持续地围绕几种固定风格进行变异和探索。这个框架为你打开了通向自动化、规模化内容创作的大门。

当然,也要时刻牢记合法合规的底线,尊重数据来源,负责任地使用AI工具。现在,代码已经就绪,灵感正在网络上游荡,是时候启动你的自动化创意流水线,去探索那片人机协作的新大陆了。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐