This guide demonstrates how to automate the addition of multiple channels to ErsatzTV using a Python script with Selenium WebDriver. If you regularly need to add a variety of channels to ErsatzTV and find the manual process time-consuming, this solution can streamline your workflow by automating channel and genre inputs.
Why Automation?
Automating the channel addition process in ErsatzTV provides several benefits:
- Efficiency: Automates repetitive tasks, saving you significant time.
- Accuracy: Reduces the risk of human error in data entry.
- Scalability: Easily manage large lists of channels, adding them consistently without additional effort.
Prerequisites
Before you start, ensure you have the following:
- Python Installation: Python must be installed on your system. Download it from Python’s official website.
- Selenium WebDriver: Selenium is a powerful tool for web browser automation. You will need the Chrome WebDriver:
- Download Chrome from ChromeDriver downloads. If using windows use chrome-win64.zip then unzip.
- Download chromedriver if using windows chromedriver-win64.zip and unzip it.
- Drop the chromedriver.exe in the chrome-win64 directory.
- Access to ErsatzTV: Ensure you have administrative access to ErsatzTV where you intend to add channels.
Setting Up Your Environment
- Install Selenium:
- Open your command line interface (CLI) and run:Copy code
pip install selenium
- Open your command line interface (CLI) and run:Copy code
- Script Configuration:
- Modify the
webdriver_path
in the script to point to where you’ve placedchromedriver.exe
.
- Modify the
Script Breakdown
The script automates these key steps:
- Initializes the Chrome WebDriver to interact with the web browser.
- Navigates to the ErsatzTV channel addition page using a predefined URL.
- Dynamically inputs the data for each channel’s name, genre, and group from a list into the ErsatzTV form. If a channel does not have a specified group, the script automatically assigns a user-defined default group.
- Submits the form for each channel entry using Selenium’s automation capabilities, ensuring that all fields are correctly filled before proceeding.
Running the Script
Prepare the Script:
- Save the provided Python script to a file named
add_channels.py
or whatever you want. - Ensure your channels list in the script is updated according to your needs, especially paying attention to the group field—if it’s empty, the default group will be used.
Execute the Script:
- Open a terminal or command prompt.
- Navigate to the directory containing
add_channels.py
. - Run the script: python3
add_channels.py
- Watch the automated browser perform the data entry on ErsatzTV.
Monitoring:
- The script will output logs in the console for each step, helping you track the automation process and troubleshoot if needed.
- Logs include confirmation messages for each field, ensuring the correct data is entered before submitting the form.
Conclusion
Using this Selenium-based script to add channels to ErsatzTV transforms a manual, repetitive task into a seamless and efficient process. The script is designed with flexibility in mind, automatically applying a default group if none is provided for a channel. Customize the script as needed to accommodate different types or numbers of channels, enhancing your productivity and data management in ErsatzTV.
Script:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
# Path to your WebDriver
webdriver_path = 'chromedriver.exe'
# User-defined default group
default_group = "Default Group"
# Initialize WebDriver
options = Options()
options.add_argument("--start-maximized") # Start maximized
service = Service(webdriver_path)
driver = webdriver.Chrome(service=service, options=options)
# URL of the web form for adding channels
url = 'http://172.30.33.15:8409/channels/add'
# Open the web page
driver.get(url)
# Allow page to load
time.sleep(2)
# Example data
channels = [
{"genre": "Comedy", "name": "LaughStream", "group": "General Entertainment"},
{"genre": "Comedy", "name": "Comedy Central", "group": "General Entertainment"},
{"genre": "Comedy", "name": "JokeBox", "group": "General Entertainment"},
{"genre": "Comedy", "name": "GiggleTV", "group": "General Entertainment"},
{"genre": "Comedy", "name": "Chuckle Channel", "group": "General Entertainment"},
# Add more channels as needed
]
for channel in channels:
try:
# Use default group if the group is not specified
group_to_use = channel["group"] if channel["group"] else default_group
# Find the third input field for the channel name
channel_name_field = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, '(//input[@type="text" and not(@readonly) and not(@disabled) and not(@placeholder)])[3]'))
)
print(f"Found input field for {channel['name']}")
# Clear the input field
channel_name_field.clear()
print("Cleared the input field")
time.sleep(0.5) # Wait a moment after clearing
# Enter the new channel name
channel_name_field.send_keys(channel["name"])
print(f"Entered {channel['name']} into the input field")
time.sleep(0.5) # Wait a moment after entering text
# Confirm the value in the field
entered_value = channel_name_field.get_attribute('value')
print(f"Value in the input field is now: {entered_value}")
# Ensure the input field is filled before proceeding
while entered_value != channel["name"]:
time.sleep(0.5)
entered_value = channel_name_field.get_attribute('value')
print(f"Rechecking value in the input field: {entered_value}")
# Find the GROUP input field (insert into categories)
group_field = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, '(//input[@type="text" and not(@readonly) and not(@disabled) and not(@placeholder)])[4]'))
)
print(f"Found input field for group {group_to_use}")
# Clear the group input field
group_field.clear()
print("Cleared the group input field")
time.sleep(0.5) # Wait a moment after clearing
# Enter the group
group_field.send_keys(group_to_use)
print(f"Entered {group_to_use} into the group field")
time.sleep(0.5) # Wait a moment after entering text
# Confirm the value in the field
entered_group = group_field.get_attribute('value')
print(f"Value in the group field is now: {entered_group}")
# Find the genre input field (insert into categories)
genre_field = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, '//input[@placeholder="Comma-separated list of categories"]'))
)
print(f"Found input field for genre {channel['genre']}")
# Enter the genre
genre_field.send_keys(channel["genre"])
print(f"Entered {channel['genre']} into the genre field")
time.sleep(0.5) # Wait a moment after entering text
# Confirm the value in the field
entered_genre = genre_field.get_attribute('value')
print(f"Value in the genre field is now: {entered_genre}")
# Ensure the genre field is filled before clicking save
while entered_genre != channel["genre"]:
time.sleep(0.5)
entered_genre = genre_field.get_attribute('value')
print(f"Rechecking value in the genre field: {entered_genre}")
# Wait a moment before clicking save
time.sleep(0.5)
# Wait until the save button is clickable and then click it
save_button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, '//button[@type="submit"]'))
)
save_button.click()
print(f"Clicked save for {channel['name']}")
# Allow time for saving and UI update
time.sleep(1)
# Open the add channel page again for the next entry
driver.get(url)
time.sleep(1)
except Exception as e:
print(f"An error occurred: {e}")
driver.quit()
break
# Close the WebDriver
driver.quit()
Here is a list off a Ton of Channels Pre-formatted.
{"genre": "Latest Movies", "name": "Epic 2024", "group": "Random Movies"},
{"genre": "Latest Movies", "name": "CinemaNow 2024", "group": "Random Movies"},
{"genre": "Latest Movies", "name": "Spotlight 2024", "group": "Random Movies"},
{"genre": "Latest Movies", "name": "Premiere 2024", "group": "Random Movies"},
{"genre": "Latest Movies", "name": "Silver Screen 2023", "group": "Random Movies"},
{"genre": "Latest Movies", "name": "Cinematic 2022", "group": "Random Movies"},
{"genre": "Latest Movies", "name": "Blockbuster 2021", "group": "Random Movies"},
{"genre": "Latest Movies", "name": "Cinematic Era 2020", "group": "Random Movies"},
{"genre": "Latest Movies", "name": "Screen Spectacle 2018", "group": "Random Movies"},
{"genre": "Latest Movies", "name": "Blockbuster Vault 2017", "group": "Random Movies"},
{"genre": "Latest Movies", "name": "NeoFlix 2016", "group": "Random Movies"},
{"genre": "Latest Movies", "name": "Screen Scene 2015", "group": "Random Movies"},
{"genre": "Latest Movies", "name": "Cinema 2013", "group": "Random Movies"},
{"genre": "Latest Movies", "name": "Flashback 2011", "group": "Random Movies"},
{"genre": "Latest Movies", "name": "Reel 2010", "group": "Random Movies"}
{"genre": "Comedy", "name": "LaughStream", "group": "General Entertainment"},
{"genre": "Comedy", "name": "Comedy Central", "group": "General Entertainment"},
{"genre": "Comedy", "name": "JokeBox", "group": "General Entertainment"},
{"genre": "Comedy", "name": "GiggleTV", "group": "General Entertainment"},
{"genre": "Comedy", "name": "Chuckle Channel", "group": "General Entertainment"},
{"genre": "Drama", "name": "TurbulentTV", "group": "General Entertainment"},
{"genre": "Drama", "name": "PassionPointe", "group": "General Entertainment"},
{"genre": "Drama", "name": "FeelTheEmotion", "group": "General Entertainment"},
{"genre": "Drama", "name": "VitalSignsTV", "group": "General Entertainment"},
{"genre": "Drama", "name": "HeartbeatTV", "group": "General Entertainment"},
{"genre": "Reality", "name": "RealWorld TV", "group": "General Entertainment"},
{"genre": "Reality", "name": "Reality Stars", "group": "General Entertainment"},
{"genre": "Reality", "name": "Survival TV", "group": "General Entertainment"},
{"genre": "Reality", "name": "House & Home", "group": "General Entertainment"},
{"genre": "Reality", "name": "Talent Quest", "group": "General Entertainment"},
{"genre": "Family", "name": "FamilyTime", "group": "General Entertainment"},
{"genre": "Family", "name": "KidsWorld", "group": "General Entertainment"},
{"genre": "Family", "name": "Adventure Kids", "group": "General Entertainment"},
{"genre": "Family", "name": "Toon Planet", "group": "General Entertainment"},
{"genre": "Family", "name": "Family Classics", "group": "General Entertainment"},
{"genre": "Crime", "name": "Crime Scene", "group": "Genre Specific"},
{"genre": "Crime", "name": "Law & Order", "group": "Genre Specific"},
{"genre": "Crime", "name": "Detective's Den", "group": "Genre Specific"},
{"genre": "Crime", "name": "Underworld", "group": "Genre Specific"},
{"genre": "Crime", "name": "CrimeWatch", "group": "Genre Specific"},
{"genre": "Horror", "name": "Nightmare Cinema", "group": "Genre Specific"},
{"genre": "Horror", "name": "HauntTV", "group": "Genre Specific"},
{"genre": "Horror", "name": "Fright Night", "group": "Genre Specific"},
{"genre": "Horror", "name": "ScreamStream", "group": "Genre Specific"},
{"genre": "Horror", "name": "Dark Shadows", "group": "Genre Specific"},
{"genre": "Science Fiction", "name": "Sci-Fi Spectrum", "group": "Genre Specific"},
{"genre": "Science Fiction", "name": "Galactic TV", "group": "Genre Specific"},
{"genre": "Science Fiction", "name": "Future Vision", "group": "Genre Specific"},
{"genre": "Science Fiction", "name": "Alien Encounters", "group": "Genre Specific"},
{"genre": "Science Fiction", "name": "CyberStream", "group": "Genre Specific"},
{"genre": "Fantasy", "name": "MythosTV", "group": "Genre Specific"},
{"genre": "Fantasy", "name": "Enchanted Realm", "group": "Genre Specific"},
{"genre": "Fantasy", "name": "FantasyQuest", "group": "Genre Specific"},
{"genre": "Fantasy", "name": "Dragon's Lair", "group": "Genre Specific"},
{"genre": "Fantasy", "name": "Mystic Lands", "group": "Genre Specific"},
{"genre": "Animation", "name": "Animotion", "group": "Niche and Special Interest"},
{"genre": "Animation", "name": "ToonTime", "group": "Niche and Special Interest"},
{"genre": "Animation", "name": "EpicToons", "group": "Niche and Special Interest"},
{"genre": "Animation", "name": "Cartoon Galaxy", "group": "Niche and Special Interest"},
{"genre": "Animation", "name": "Animagic", "group": "Niche and Special Interest"},
{"genre": "Adult Cartoons", "name": "Nocturne Animations", "group": "Niche and Special Interest"},
{"genre": "Adult Cartoons", "name": "Outlaw Toons", "group": "Niche and Special Interest"},
{"genre": "Adult Cartoons", "name": "Twisted Laughs", "group": "Niche and Special Interest"},
{"genre": "Adult Cartoons", "name": "PsycheToons", "group": "Niche and Special Interest"},
{"genre": "Adult Cartoons", "name": "Retro Rebellion", "group": "Niche and Special Interest"},
{"genre": "Adult Cartoons", "name": "DarkHumor TV", "group": "Niche and Special Interest"},
{"genre": "Adult Cartoons", "name": "MatureToons", "group": "Niche and Special Interest"},
{"genre": "Adult Cartoons", "name": "WickedCartoons", "group": "Niche and Special Interest"},
{"genre": "Adult Cartoons", "name": "Edgy Animation", "group": "Niche and Special Interest"},
{"genre": "Adult Cartoons", "name": "RebelToons", "group": "Niche and Special Interest"}
{"genre": "Documentaries", "name": "Insight Films", "group": "Niche and Special Interest"},
{"genre": "Documentaries", "name": "TrueVision", "group": "Niche and Special Interest"},
{"genre": "Documentaries", "name": "LifeDoc", "group": "Niche and Special Interest"},
{"genre": "Documentaries", "name": "DocuWorld", "group": "Niche and Special Interest"},
{"genre": "Documentaries", "name": "Deep Dive", "group": "Niche and Special Interest"},
{"genre": "Biography", "name": "BioPix", "group": "Niche and Special Interest"},
{"genre": "Biography", "name": "Life Stories", "group": "Niche and Special Interest"},
{"genre": "Biography", "name": "Portraits TV", "group": "Niche and Special Interest"},
{"genre": "Biography", "name": "Icons Network", "group": "Niche and Special Interest"},
{"genre": "Biography", "name": "Legendary Lives", "group": "Niche and Special Interest"},
{"genre": "Adventure", "name": "Questline", "group": "Action and Adventure"},
{"genre": "Adventure", "name": "Journey TV", "group": "Action and Adventure"},
{"genre": "Adventure", "name": "Adventure Realm", "group": "Action and Adventure"},
{"genre": "Adventure", "name": "Explorer's Edge", "group": "Action and Adventure"},
{"genre": "Adventure", "name": "Epic Trails", "group": "Action and Adventure"},
{"genre": "Adventure", "name": "Frontier TV", "group": "Action and Adventure"},
{"genre": "Adventure", "name": "Odyssey Channel", "group": "Action and Adventure"},
{"genre": "Action", "name": "Adrenaline Rush", "group": "Action and Adventure"},
{"genre": "Action", "name": "Strike Force TV", "group": "Action and Adventure"},
{"genre": "Action", "name": "Action Zone", "group": "Action and Adventure"},
{"genre": "Action", "name": "PowerPlay", "group": "Action and Adventure"},
{"genre": "Action", "name": "Impact TV", "group": "Action and Adventure"},
{"genre": "Action", "name": "Shockwave", "group": "Action and Adventure"},
{"genre": "Action", "name": "TurboMax", "group": "Action and Adventure"},
{"genre": "Action", "name": "Combat Kings", "group": "Action and Adventure"},
{"genre": "War", "name": "Battlefront TV", "group": "Action and Adventure"},
{"genre": "War", "name": "Warriors' Legacy", "group": "Action and Adventure"},
{"genre": "War", "name": "Conflict Chronicles", "group": "Action and Adventure"},
{"genre": "War", "name": "ValorTV", "group": "Action and Adventure"},
{"genre": "War", "name": "WarZone", "group": "Action and Adventure"},
{"genre": "War", "name": "Patriot Films", "group": "Action and Adventure"},
{"genre": "War", "name": "The Frontline", "group": "Action and Adventure"},
{"genre": "Medical", "name": "MedixTV", "group": "Special Themes"},
{"genre": "Medical", "name": "HealthScape", "group": "Special Themes"},
{"genre": "Medical", "name": "VitalSigns", "group": "Special Themes"},
{"genre": "Medical", "name": "MediVision", "group": "Special Themes"},
{"genre": "Medical", "name": "DocuMed", "group": "Special Themes"},
{"genre": "Medical", "name": "ER Chronicles", "group": "Special Themes"},
{"genre": "Medical", "name": "Pulse Network", "group": "Special Themes"},
{"genre": "Medical", "name": "MediStream", "group": "Special Themes"},
{"genre": "Medical", "name": "The Med Channel", "group": "Special Themes"},
{"genre": "Medical", "name": "ER TV", "group": "Special Themes"},
{"genre": "Medical", "name": "LifeLine", "group": "Special Themes"},
{"genre": "Medical", "name": "VitalWatch", "group": "Special Themes"},
{"genre": "Medical", "name": "MediFocus", "group": "Special Themes"},
{"genre": "Medical", "name": "CureTV", "group": "Special Themes"},
{"genre": "Marijuana", "name": "Cannabis Chronicles", "group": "Special Themes"},
{"genre": "Marijuana", "name": "GreenWave TV", "group": "Special Themes"},
{"genre": "Marijuana", "name": "The High Life", "group": "Special Themes"},
{"genre": "Marijuana", "name": "BlazeTV", "group": "Special Themes"},
{"genre": "Marijuana", "name": "Weed World", "group": "Special Themes"},
{"genre": "Marijuana", "name": "HerbVision", "group": "Special Themes"},
{"genre": "Music and Musicals", "name": "Hits & Classics", "group": "Music and Musicals"},
{"genre": "Music and Musicals", "name": "RockOn TV", "group": "Music and Musicals"},
{"genre": "Music and Musicals", "name": "Rhythm & Blues", "group": "Music and Musicals"},
{"genre": "Music and Musicals", "name": "PopNation", "group": "Music and Musicals"},
{"genre": "Music and Musicals", "name": "Indie Beats", "group": "Music and Musicals"},
{"genre": "Music and Musicals", "name": "MelodyTV", "group": "Music and Musicals"},
{"genre": "Music and Musicals", "name": "SingAlong", "group": "Music and Musicals"},
{"genre": "Music and Musicals", "name": "Broadway Classics", "group": "Music and Musicals"},
{"genre": "Music and Musicals", "name": "DanceFloor", "group": "Music and Musicals"},
{"genre": "Music and Musicals", "name": "Harmony Channel", "group": "Music and Musicals"},
{"genre": "Food", "name": "Culinary Creations", "group": "Niche and Special Interest"},
{"genre": "Food", "name": "Foodie Network", "group": "Niche and Special Interest"},
{"genre": "Food", "name": "BakeTV", "group": "Niche and Special Interest"},
{"genre": "Food", "name": "Gourmet Adventures", "group": "Niche and Special Interest"},
{"genre": "Food", "name": "Healthy Eats", "group": "Niche and Special Interest"},
{"genre": "Home Improvement", "name": "HomeRevive", "group": "Niche and Special Interest"},
{"genre": "Home Improvement", "name": "Fixer Upper TV", "group": "Niche and Special Interest"},
{"genre": "Home Improvement", "name": "DIY Dream", "group": "Niche and Special Interest"},
{"genre": "Home Improvement", "name": "Renovation Nation", "group": "Niche and Special Interest"},
{"genre": "Home Improvement", "name": "Home & Garden TV", "group": "Niche and Special Interest"}
Download all logos there are multiple of each. If any are missing or you have ideas for more just leave a comment!
Expand to view all Channel Logos