Part 5 of "Replacing UWSC with Python". This time we will actually make a robot. I couldn't post for a while due to various reasons.
Like the last time, I wrote it while checking it, so I think there are some mistakes. In that case, please make a Bishibashi edit request (sweat)
When I searched on UWSC, it seems that it was supplemented by the following site, so I will try to implement the desired function written in the forum.
CSWU-What to do Compatible system without UWSC https://wiki3.jp/CSWU
last time Replace UWSC with Python (4) Cheat Sheet [2] next time undecided </ font>
We will create some of the features that UWSC does not have in this environment. The function to make is
―― 1. Image search (focus) highlight ―― 2. Element search (focus) highlight --3. GETID / CLKITEM compatibility function
In addition, the following sites were very helpful in creating the functions. If you have a function you want to create, you should refer to it.
Python Example https://www.programcreek.com/python/
When you search for images, you can easily understand where on the screen the match was made by drawing a rectangle on the screen.
If you import win32gui and give (left, top, right, bottom), it will highlight the detected location. If you want to change the line type or color of the rectangle, you need to set it with win32ui.CreatePen
, win32api.RGB
, pyhandle
, win32con
.
func_dhlight.py
import win32gui
##Desktop highlights
def dhlight(x1, y1, x2, y2):
hwnd=win32gui.WindowFromPoint((x1,y1))
hdc=win32gui.GetDC(hwnd)
rc=(x1, y1, x2, y2)
win32gui.DrawFocusRect(hdc, rc)
win32gui.ReleaseDC(hwnd,hdc)
if __name__ == '__main__':
##It feels like using it in combination with pyautogui's locateOnScreen.
##However, locateOnScreen is Box(left, top, width, height)Because it returns
pos_x,pos_y,size_w,size_h = pyautogui.locateOnScreen('target.png')
x1 = pos_x
y1 = pos_y
x2 = pos_x + size_w
y2 = pos_y + size_h
dhlight(x1, y1, x2, y2)
##If you write, target.A dotted rectangle will be displayed where the png is found.
When searching for an element on the browser, it will highlight which element was selected. Since this uses css insertion of selenium, it may not respond in the case of dynamic UI / UX or prohibiting rewriting of css (it is better to draw with win32gui by taking the coordinates of the element. maybe) I just plugged in css ("background: white; border: 1px solid blue;"), so I can change it to my liking.
func_hhlight.py
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
##Highlights of Html Element
def hhlight(element):
driver = element._parent
def apply_style(s):
driver.execute_script("arguments[0].setAttribute('style', arguments[1]);",element, s)
original_style = element.get_attribute('style')
apply_style("background: white; border: 1px solid blue;")
time.sleep(.3)
apply_style(original_style)
if __name__ == '__main__':
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.set_page_load_timeout(5)
driver.set_script_timeout(5)
driver.get('https://www.google.com/')
##Like this, when you search for an element and pass the element to the created function, the specified CSS is applied,
##You will be able to see which element is selected
search_box = driver.find_element_by_name("q")
hhlight(search_box)
In UWSC, I used GETID to get the window ID and operated it, but it is difficult to do this in Python as it is, so I used a function to get the process ID from the window name (get_pid) and get the window handle from the process ID (get_hwnds). I decided to make it and deal with it.
func_getid.py
import os,sys,re,time,subprocess
import win32api, win32gui, win32con, win32process
def get_pid(title):
hwnd = win32gui.FindWindow(None, title)
threadid,pid = win32process.GetWindowThreadProcessId(hwnd)
return pid
def get_hwnds(pid):
def callback(hwnd, hwnds):
if win32gui.IsWindowVisible(hwnd) and win32gui.IsWindowEnabled(hwnd):
_, found_pid = win32process.GetWindowThreadProcessId(hwnd)
if found_pid == pid:
hwnds.append(hwnd)
return True
hwnds = []
win32gui.EnumWindows(callback, hwnds)
return hwnds
def clkitem(win_title,itemid):
#Search by window title
hwnd = win32gui.FindWindow(0, win_title)
#List items in the window
inplay_children = []
def is_win_ok(hwnd, *args):
s = win32gui.GetWindowText(hwnd)
inplay_children.append(hwnd)
win32gui.EnumChildWindows(hwnd, is_win_ok, None)
#Specify the item ID number and item/Get the handle of the button
button_hwnd = inplay_children[itemid]
#Activate the window
win32gui.SetForegroundWindow(hwnd)
#Click the specified button (press)->Send release)
win32api.PostMessage(button_hwnd, win32con.WM_LBUTTONDOWN, 0, 0)
win32api.PostMessage(button_hwnd, win32con.WM_LBUTTONUP, 0, 0)
#Get the process ID from the window ID
pid = get_pid(u"calculator")
#Click the first button on the calculator
clkitem(u"calculator",1)
#Get the handle from the process ID and operate[GETCTLHND]Equivalent to
for hwnd in get_hwnds(pid):
if hwnd == 0:
print(u"Window not found")
else:
#Size specification(resize)
win32gui.MoveWindow(hwnd, 100, 100, 500, 500, True)
#Maximize
win32gui.ShowWindow(hwnd, win32con.SW_MAXIMIZE)
time.sleep(1)
#close
win32gui.SendMessage(hwnd,win32con.WM_CLOSE,0,0)
You can now resize, move, and focus native apps on your screen. As far as the browser is concerned, it's easier to go with selenium.
The part enclosed in [] is the module name to be used.
--1. Load ini (setting.ini) containing login information: [ConfigParser] --2 Open the browser, maximize it, and then go to the ini login_url: [Selenium] --3. Login using login information: [Selenium] --4. Move to the specified screen (post): [Selenium / win32gui] --5. Open the Excel file containing the entry information list [xlrd] --6.1 Line by line posted to input form [Selenium] ―― 7. When the last line of the Excel file is detected, close the screen and exit [Selenium]
setting.ini
[Server]
login_id = user01
login_pw = password
login_url = https://127.0.0.1/wp/wp-login.php
[SitePage]
write_fourm =Post
[WriteFile]
excel_file = input_list.xlsx
input_list.xlsx
[Sheet1]
title,text,tag,format
Test 1,First post 1,Uncategorized,standard
Test 2,First post 2,Uncategorized,standard
Test 3,First post 3,Uncategorized,standard
Test 4,First post 4,Uncategorized,standard
Test 5,First post 5,Uncategorized,standard
Test 6,First post 6,Uncategorized,standard
Actually, I will write the source according to the scenario. Actually, I should make more functions and make them easier to read, but I wrote them flat so that the scenario can be easily followed. Please note that it is written in UTF-8.
wordpress_auto_post.py
# -*- coding: utf-8 -*-
#Module loading
import os,sys,re,time,subprocess
import pyautogui
import win32gui
import configparser
import xlrd
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.alert import Alert
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.select import Select
##Desktop highlights
def dhlight(x1, y1, x2, y2):
hwnd=win32gui.WindowFromPoint((x1,y1))
hdc=win32gui.GetDC(hwnd)
rc=(x1, y1, x2, y2)
win32gui.DrawFocusRect(hdc, rc)
win32gui.ReleaseDC(hwnd,hdc)
##Highlights of Html Element
def hhlight(element):
driver = element._parent
def apply_style(s):
driver.execute_script("arguments[0].setAttribute('style', arguments[1]);",element, s)
original_style = element.get_attribute('style')
apply_style("background: white; border: 1px solid blue;")
time.sleep(.3)
apply_style(original_style)
#Read configuration file
CONF_FILEPATH = 'setting.ini'
config = configparser.ConfigParser()
config.read( CONF_FILEPATH, 'UTF-8')
#In the conf file[]Specify the place surrounded by
config_server = config['Server']
config_page = config['SitePage']
config_excel = config['WriteFile']
#In conf[]Get the contents that contain variables and data under
uid = config_server['login_id']
upw = config_server['login_pw']
url = config_server['login_url']
search_button = config_page['write_fourm']
xlsxfile = config_excel['excel_file']
##Initialize Chrome
options = Options()
##Chrome path (usually no need to specify, when using portable version etc. or stable/When switching beta)
options.binary_location = 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
options.add_argument('--start-maximized')
options.add_argument('--disable-gpu')
##Create a Chrome WebDriver object.
driver = webdriver.Chrome(options=options,executable_path="C:\Python37\chromedriver.exe")
#Waiting time until the element is found, can be specified only immediately after driver generation
driver.implicitly_wait(10)
#Specify to wait up to 5 seconds for the page to fully load, only immediately after driver generation
driver.set_page_load_timeout(5)
#Specify to wait up to 5 seconds until Javascript execution finishes
driver.set_script_timeout(5)
#URL move
driver.get(url)
#Login process
user_id_elm = driver.find_element_by_id("user_login")
#Element highlight
hhlight(user_id_elm)
user_id_elm.send_keys(uid)
user_pw_elm = driver.find_element_by_id("user_pass")
hhlight(post_fourm)
user_pw_elm.send_keys(upw)
login_submit = driver.find_element_by_id("wp-submit")
hhlight(post_fourm)
login_submit.submit()
time.sleep(5)
#Post
menu_post_elm = driver.find_element_by_xpath("/html/body/div[1]/div[1]/div[2]/ul/li[3]/a/div[3]")
hhlight(menu_post_elm)
menu_post_elm.click()
time.sleep(2)
#New addition
new_post_elm = driver.find_element_by_xpath("/html/body/div[1]/div[2]/div[2]/div[1]/div[3]/a")
hhlight(new_post_elm)
new_post_elm.click()
time.sleep(2)
#Open excel file
wb = xlrd.open_workbook(xlsxfile)
#Sheet designation
sheet = wb.sheet_by_name('sheet1')
#Last line detection
last_row = sheet.nrows
#Read into a two-dimensional array of all rows(If you don't have enough memory, you should read line by line)
readcells = [sheet.row_values(row) for row in range(sheet.nrows)]
time.sleep(5)
#Article title
card_title_elm = driver.find_element_by_xpath("//*[@id='post-title-0']")
#Article Text
card_body_elm = driver.find_element_by_xpath("/html/body/div[1]/div[2]/div[2]/div[1]/div[3]/div[1]/div/div/div/div[2]/div[3]/div/div[1]/div/div/div[2]/div[1]/div[3]/div/div/div/div/div/div/p")
#Exit driver
driver.close()
python ./wordpress_auto_post.py
It should move and be posted without any problems.
It really hurts to lose UWSC, and I hope there will be simpler automation tools. Next time, if I come up with something, I'll write a sequel.
Recommended Posts