I'm trying to use Python to PUBLISH and EDIT a new posting on wordpress.com?
I'm able to login with my username and password and also get to the new wordpress.com posting page loaded using the following SELENIUM PYTHON code.
However for some reason i'm not able to select the title field... is there an easier way to get the CSS SELECTOR? or element id? it maybe that its being created dynamically and wont show up "normally?" Here is the bug in the code?
title_field = WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'h1.wp-block')))
enter_text(title_field, title)
here is the full python code i'm using...
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
def list_my_sites(driver):
try:
# Navigate to "My Sites" after successful login
my_sites_link = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "a.masterbar__item:nth-child(2)"))
)
my_sites_link.click()
# Wait for the table to be present (adjust timeout as needed)
table_body = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".dataviews-view-table > tbody")) # Use a more general selector for the table body
)
# Get all rows in the table body
rows = table_body.find_elements(By.TAG_NAME, "tr")
first_column_data = []
for row in rows:
try: # Handle potential errors if a row doesn't have enough columns
first_cell = row.find_element(By.CSS_SELECTOR, "td:nth-child(1)") # Get the first cell (column) in each row
first_column_data.append(first_cell.text) # extract the text from that cell
except: #NoSuchElementException:
print("Skipping a row, its missing a first cell")
print (first_column_data)
except Exception as e:
print(f"Error listing sites: {e}")
def create_and_publish_post(driver, title, content, tags=None, category=None, featured_image_path=None):
def enter_text(element, text): # Helper function for reliable text entry
element.click()
action = webdriver.ActionChains(driver)
action.send_keys(text).perform()
try:
# 1. Navigate to "Add New Post"
driver.get(website + "/wp-admin/post-new.php") # Or your "Add New" URL
# 2. Enter title
title_field = WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'h1.wp-block')))
enter_text(title_field, title)
# 3. Enter content (Gutenberg)
content_field = WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.CSS_SELECTOR, ".block-editor-rich-text__editable")))
enter_text(content_field, content)
# 4. Add tags (if provided)
if tags:
tag_field = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "tags-input")))
for tag in tags:
enter_text(tag_field, tag)
tag_field.send_keys(Keys.ENTER)
# 5. Add category (if provided) # New feature!
if category:
category_field = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "category-add-toggle")) # This will vary a lot across sites, INSPECT YOURS.
)
category_field.click() # click on the button first
category_input_field = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "new-category-name")) # sometimes there is an input for adding new categories
)
enter_text(category_input_field, category) # type in the category you want
category_input_field.send_keys(Keys.ENTER) # select the newly added category
# 6. Add featured image (if provided) # New feature!
if featured_image_path:
featured_image_button = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".editor-post-featured-image__toggle")) # Click to open the Featured Image settings
).click()
upload_button = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".components-button.editor-post-featured-image__upload-button")) # This one is tricky, it tends to have a dynamic ID, better to use a more broad selector
)
upload_button.send_keys(featured_image_path) # Send the path directly to the upload button
# 7. Publish
WebDriverWait(driver, 15).until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".editor-post-publish-panel__toggle"))).click() # Open publish panel
WebDriverWait(driver, 15).until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".editor-post-publish-button"))).click() # Publish
print("Post published successfully!")
except Exception as e:
print(f"Error publishing post: {e}")
def wordpress_login(username, password):
try:
# Initialize the WebDriver (replace with your browser's driver)
driver = webdriver.Firefox() # Or webdriver.Chrome(), etc.
# Go to the WordPress.com login page
driver.get("https://wordpress.com/log-in")
# Wait for the username field to be visible and enter the username
username_field = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "usernameOrEmail"))
)
username_field.send_keys(username)
# Continue button
continue_button = driver.find_element(By.CSS_SELECTOR, "button[type='submit']")
continue_button.click()
# Wait for password field after continue button
password_field = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "password"))
)
password_field.send_keys(password)
# Log in button
log_in_button = driver.find_element(By.CSS_SELECTOR, "button[type='submit']")
log_in_button.click()
# Add a wait to ensure the login is complete (adjust as needed)
time.sleep(5) # You might need a more robust check here
# Check for successful login (example, adjust based on your site's structure)
# You might check for a specific element on the logged-in page
try:
check_button = driver.find_element(By.CSS_SELECTOR, "a.masterbar__item:nth-child(2) > svg:nth-child(1) > g:nth-child(1) > path:nth-child(1)")
print("Login successful!")
except:
print("Login failed. Check credentials or website structure.")
#list_my_sites(driver)
create_and_publish_post(driver, "hello!", "world!!!")
except Exception as e:
print(f"An error occurred: {e}")
finally:
# Close the browser window
# driver.quit()
print("all done?!")
if __name__ == "__main__":
username = "username" # Replace with your username
password = "password" # Replace with your password
website = "https://ashercmartin.wordpress.com" # Replace with your wordpress website
wordpress_login(username, password)
I wasn't able to find the precise CSS SELECTOR however i was able to publish a posting with this code. One possible reason is a WORDPRESS shadow DOM???
def create_and_publish_post(driver, title, content, tags=None, category=None, featured_image_path=None):
def enter_text(element, text): # Helper function for reliable text entry
element.click()
action = webdriver.ActionChains(driver)
action.send_keys(text).perform()
try:
# 1. Navigate to "Add New Post"
driver.get(website + "/wp-admin/post-new.php") # Or your "Add New" URL
time.sleep(2)
#works! add a new block!
#new_block = WebDriverWait(driver, 15).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.components-button > svg:nth-child(1)')))
#new_block.click()
action = webdriver.ActionChains(driver)
#action.send_keys(title + " " + content).perform()
#action.send_keys(Keys.ENTER).perform()
#action.send_keys("whats up!!!").perform()
#change format style to html / code
select = WebDriverWait(driver, 15).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.components-dropdown:nth-child(6) > button:nth-child(1) > svg:nth-child(1)"))).click() # Open publish panel
#make sure code edit is selected button.components-menu-items-choice:nth-child(2) > span:nth-child(1)
select_code = WebDriverWait(driver, 15).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.components-menu-items-choice:nth-child(2) > span:nth-child(1)"))).click() # Open publish panel
#update title #inspector-textarea-control-0
select_title = WebDriverWait(driver, 15).until(EC.element_to_be_clickable((By.ID, "inspector-textarea-control-0"))).click() # Open publish panel
action.send_keys("awesome title!").perform()
#select text / html #post-content-2
select_content = WebDriverWait(driver, 15).until(EC.element_to_be_clickable((By.ID, "post-content-0"))).click() # Open publish panel
action.send_keys("whats up!!!").perform()
# 7. Publish button.components-button:nth-child(5)
WebDriverWait(driver, 15).until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".editor-post-publish-panel__toggle"))).click() # Open publish panel
WebDriverWait(driver, 15).until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".editor-post-publish-button"))).click() # Publish
print("Post published successfully!")
except Exception as e:
print(f"Error publishing post: {e}")
thanks for the help! what i needed to do was change to HTML/CODE view and then select the details from there ... for some reason the default view i couldn't use a valid CSS SELECTOR.
;)