Bulk image generation script – Piclumen
To work comfortably, you need to use mass actions, and when generating images, these manipulations will play a key role, especially when publishing a large number of posts. Today let’s look at a script for generating photos by text queries directly through a list in a text file, but let’s talk about everything in order.
Nowadays there are a huge number of sites and just image generation utilities, but most of them are paid solutions, and we will use a completely free site (piclumen.com) and code accordingly.
Create a text file, for example, ‘queries.txt’ and write the necessary queries line by line into it. All actions are performed in a separate folder, having previously created a virtual environment.
py -m venv .venv
.venv\Scripts\activate
Also enter data into the file ‘.env’ for authorization on the site (register on it in advance).
LOGIN=login
PASSWORD=password
Next, create the main file (main.py) with the code:
# pip install python-dotenv
# pip install botasaurus
from botasaurus.browser import browser, Driver, Wait
import os
import time
from dotenv import load_dotenv
import pyperclip
import requests
from io import BytesIO
from PIL import Image
# Global counter for images
global_image_counter = 0
# Number of images for download
num_images_to_download = 4 # Например, загрузить 4 изображения из каждого запроса
# Loading variables from .env
load_dotenv()
login = os.getenv("LOGIN")
password = os.getenv("PASSWORD")
Specify the path to the file and directory where we will store the photos.
# File folder
base_dir = os.path.dirname(__file__)
images_dir = os.path.join(base_dir, 'images')
# Create folders if they do not exist
os.makedirs(images_dir, exist_ok=True)
Record the site address for authorization and the main url for queries headers and so on.
# URL для входа и получения данных
login_url = 'https://piclumen.com/app/account'
dashboard_url = 'https://piclumen.com/app/image-generator/create'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36'
}
# Login and password
login_data = {
'email': os.getenv("LOGIN"),
'password': os.getenv("PASSWORD")
}
We will use the ‘botasaurus‘ library, as I personally like it better than selenium. We write the main function that will be responsible for logging into the site and performing basic actions.
@browser(
# add_arguments=['--headless=new'],
wait_for_complete_page_load=False,
reuse_driver=True
)
def piclumen(driver: Driver, data):
global global_image_counter # Используем глобальный счетчик
try:
driver.get(login_url, wait=5)
driver.type('input[placeholder="Email"]', login, wait=1)
driver.type('input[placeholder="Password"]', password, wait=1)
driver.click('#app > div > div.content.overflow-x-hidden.dark > div.absolute.pb-16.top-0.left-0.w-screen.min-h-full.h-max.flex.justify-center.items-center.text-white > div.w-full.md\:w-\[488px\].relative.z-10.bg-black\/50.opacity-90.backdrop-blur-3xl.mb-24.md\:mb-0.md\:rounded-3xl.overflow-hidden > div > div.w-80.mx-auto.sign-in-account > div > div.mt-8.w-full > button', wait=5)
driver.get(dashboard_url, wait=10)
# settings
driver.click('#app > div > div.flex.h-screen.box-border.dark\:bg-black.bg-zinc-200.max-md\:flex-wrap-reverse > div.w-full.relative > div > div.h-screen.relative.scroll-box.overflow-y-auto.flex > div.shrink-0.h-full > div > div > div.tool-bar-item', wait=3)
# Read requests from the file
queries = read_queries_from_file(os.path.join(base_dir, 'queries.txt')) # путь к вашему файлу с запросами
for query in queries:
if not query:
continue
print(f"Processing the request: {query}")
if query: # Проверяем, что запрос не пустой
try:
# 4 images per iteration
driver.click('#confExtendArea > div > div.flex.gap-4.shrink-0.ml-2 > div:nth-child(3) > div > div:nth-child(4)', wait=3)
# # settings input
# driver.type('#app > div > div.flex.h-screen.box-border.dark\:bg-black.bg-zinc-200.max-md\:flex-wrap-reverse > div.w-full.relative > div > div.h-screen.relative.scroll-box.overflow-y-auto.flex > div.shrink-0.h-full > div > div.border-r.p-4.border-solid.dark\:border-dark-bg-2.w-\[336px\] > div > div:nth-child(1) > div.mt-1.rounded-lg.relative.dark\:bg-dark-bg-2.bg-white.w-full.pb-2 > div > div > div.n-input__textarea.n-scrollbar > textarea', negative_prompt, wait=1)
# if guidance is not None:
# driver.type('#app > div > div.flex.h-screen.box-border.dark\:bg-black.bg-zinc-200.max-md\:flex-wrap-reverse > div.w-full.relative > div > div.h-screen.relative.scroll-box.overflow-y-auto.flex > div.shrink-0.h-full > div > div.border-r.p-4.border-solid.dark\:border-dark-bg-2.w-\[336px\] > div > div:nth-child(2) > div.mt-1.flex.items-center.gap-2 > div.n-input-number.w-32.rounded-lg.shrink-0.text-center.dark\:bg-dark-bg-2.bg-white.input-number-h-32 > div > div.n-input-wrapper > div.n-input__input > input', guidance, wait=1)
# if seed is not None:
# driver.click('#app > div > div.flex.h-screen.box-border.dark\:bg-black.bg-zinc-200.max-md\:flex-wrap-reverse > div.w-full.relative > div > div.h-screen.relative.scroll-box.overflow-y-auto.flex > div.shrink-0.h-full > div > div.border-r.p-4.border-solid.dark\:border-dark-bg-2.w-\[336px\] > div > div:nth-child(4) > div > div.mt-1.flex.items-center.gap-2 > div.seed-group > div:nth-child(2) > span', wait=1)
# driver.type('#app > div > div.flex.h-screen.box-border.dark\:bg-black.bg-zinc-200.max-md\:flex-wrap-reverse > div.w-full.relative > div > div.h-screen.relative.scroll-box.overflow-y-auto.flex > div.shrink-0.h-full > div > div.border-r.p-4.border-solid.dark\:border-dark-bg-2.w-\[336px\] > div > div:nth-child(4) > div > div.mt-1.flex.items-center.gap-2 > div.w-32.rounded-lg.dark\:bg-dark-bg-2.bg-white.border-solid.border-red-500.border > input', seed, wait=1)
# Image generation request
driver.type('textarea', query, wait=2)
# Click on Generate
driver.click(f'#confExtendArea > div > div.mt-3.flex.items-center.gap-2\.5.shrink-0 > div > div.flex.gap-3 > button > span', wait=3)
time.sleep(80)
normal_urls = process_image_links(driver, images_dir)
# Downloading and saving images
for url in normal_urls[:num_images_to_download]: # Ограничиваем количество изображений
try:
# Download the image
response = requests.get(url)
response.raise_for_status() # Проверка на ошибки
# Open the image
img = Image.open(BytesIO(response.content))
# Use a global counter for the file name
global_image_counter += 1
# Convert to PNG and save
output_path = os.path.join(images_dir, f"image_{global_image_counter}.png")
img.save(output_path, 'PNG')
print(f"Saved image: {output_path}")
except Exception as e:
print(f"Failed to save image by URL {url}: {e}")
except Exception as e:
print(f"Error during request processing '{query}': {e}")
continue # Proceed to the next query if an error occurred
except Exception as e:
print(f"Error on page: {e}")
# Launch the browser
piclumen()
All the code is commented out, so it should make sense to you if you understand python. A brief description of the function: go to the site on the authorization page, log in, then read the line with the request and enter it in the required input field. Click on the generate button and wait for the images to be received, then download them and move on to the next request in the list.
Professional data parsing via ZennoPoster, Python, creating browser and keyboard automation scripts. SEO-promotion and website creation: from a business card site to a full-fledged portal.