Open maykel535 opened 2 years ago
you should use webdriver.find_element("name", VALUE) instead
I have the same problem
I'm also having this problem, any way to fix it?
noip-renew.txt Copy the contents of the txt file and paste it in noip-renew.py. Copy the created file into /usr/local/bin/ and replace the existing file.
Modified the noip-renew.py as per @juniorik
noip-renew.txt Copy the contents of the txt file and paste it in noip-renew.py. Copy the created file into /usr/local/bin/ and replace the existing file.
Modified the noip-renew.py as per @juniorik
I was having the same issue as maykel535 and tried the script you posted. It got further than before but still having errors. Pasted the output below minus the IP that it was showing.
[2023/07/02 15:25:44] - Debug level: 2 [2023/07/02 15:25:44] - Opening https://www.noip.com/login... [2023/07/02 15:25:47] - Logging in... [2023/07/02 15:25:48] - Message: element not interactable (Session info: headless chrome=...) Stacktrace:
@TarkinMX I'm also facing the same issue.
I am have same issue as @TarkinMX
noip-renew.txt So it determined that the whole thing is pretty much bungled.
The initial script that @adithyapi4 issued fixed part of the problem. The xauth element grabs need to be updated as well, same format he used would apply. host.find_element_by_xpath(".//a[@class='link-info cursor-pointer']") would be host.find_element("xauth", ".//a[@class='link-info cursor-pointer']"). I used an imported library to be more intuitive, so my command looks like this host.find_element(By.XAUTH, ".//a[@class='link-info cursor-pointer']").
I also found the noip-renew-skd.sh script used to update cronjob will update the next cronjob to the past so I fixed that in the .py script. The line in question is Line 117, it uses current month to set the next cronjob which end up putting it in the past. I changed from month = str(today.month) to *** . I ended up updated noip-renew-skd.sh to also update the cronjob to properly dump the print statements as well as run the cronjob on my raspberry pi4. The cronjob was formatted to as "30 0 $1 $2 $USER $INSTEXE $LOGDIR", I ended up with "30 0 $1 $2 * $INSTEXE >> $LOGDIR 2>&1". Keep in mind the logs ownership needs to be rw for $USER.
I uploaded the noip-renew.py script I am currently using and is working for me in the .txt file, I also left some of my debug lines in there in case people might want to figure out there own new issues and have a starting point.
All in all, this script works great after the fixes. I assume some kind of update occurred with the Selenium webdriver or chrome because I setup roughly 1 month ago and it worked but 30 days later when noip needed a renewal it did not function. If anyone has question feel free to ask, I dumped 24 straight hours into these scripts and I am feeling proficient. HAHAHA
@ECLAYA4188 Thank you for the update, it works great here.
@ECLAYA4188 Can you post the working script
I tried the script on WSL, but it didn't detect any hosts :(
user@MyPC:/usr/local/bin$ bash noip-renew-user.sh
[2023/08/13 14:18:04] - Debug level: 2
[2023/08/13 14:18:04] - Opening https://www.noip.com/login...
[2023/08/13 14:18:07] - Logging in...
[2023/08/13 14:18:12] - Opening https://my.noip.com/dynamic-dns...
[2023/08/13 14:18:16] - No hosts or host table rows not found
I tried looking for the screenshots where selenium is supposed to be saving them, but couldn't find them.
def get_hosts(self):
host_tds = self.browser.find_elements(By.XPATH, "//td[@class=\"word-break-col\"]")
self.browser.save_screenshot("end.png")
if len(host_tds) == 0:
raise Exception("No hosts or host table rows not found")
return host_tds
@ECLAYA4188 As you are the expert one :D, do you have any idea why is not finding any hosts? I definitely have one under Dynamic DNS --> no-ip Hostnames
Sorry for the delay, I have been heavy in the proxy game these days MITM type garbage :P
@redespace I suspect you were tinkering with the xpath search strings and forgot to change some back... I also redirected the browser in parts of the code but after initial login the script depends on the webpage being "https://my.noip.com/dynamic-dns", maybe you redirected somewhere prior on accident. I did this when I was troubleshooting and got the same error. I can assure you all search strings function as intended. The major issue with the original script I believe to be that the selenium web-driver updated and deprecated some methods and syntax.
Another unrelated that I have had battles with in the past but no longer have this issue because all my pi's are hardwired is the webpage needs to fully load after each action. this is where the script delay comes in handy. after each page interaction ("click", "enter", etc) hard code a delay this might help if you are not hardwired.
@adithyapi4 Here is function script, github is doing some wierd formatting so I indicated beginning and end of script
from selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import TimeoutException from datetime import date from datetime import timedelta import time import sys import os import re import base64 import subprocess
class Logger: def init(self, level): self.level = 0 if level is None else level
def log(self, msg, level=None):
self.time_string_formatter = time.strftime('%Y/%m/%d %H:%M:%S', time.localtime(time.time()))
self.level = self.level if level is None else level
if self.level > 0:
print(f"[{self.time_string_formatter}] - {msg}")
class Robot:
USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0"
LOGIN_URL = "https://www.noip.com/login"
HOST_URL = "https://my.noip.com/dynamic-dns"
def __init__(self, username, password, debug):
self.debug = debug
self.username = username
self.password = password
self.browser = self.init_browser()
self.logger = Logger(debug)
@staticmethod
def init_browser():
options = webdriver.ChromeOptions()
#added for Raspbian Buster 4.0+ versions. Check https://www.raspberrypi.org/forums/viewtopic.php?t=258019 for reference.
options.add_argument("disable-features=VizDisplayCompositor")
options.add_argument("headless")
options.add_argument("no-sandbox") # need when run in docker
options.add_argument("window-size=1200x800")
options.add_argument(f"user-agent={Robot.USER_AGENT}")
options.add_argument('disable-extensions')
if 'https_proxy' in os.environ:
options.add_argument("proxy-server=" + os.environ['https_proxy'])
browser = webdriver.Chrome(options=options)
browser.set_page_load_timeout(90000) # Extended timeout for Raspberry Pi.
return browser
def login(self):
self.logger.log(f"Opening {Robot.LOGIN_URL}...")
self.browser.get(Robot.LOGIN_URL)
time.sleep(1)
#html = self.browser.page_source
#print (html)
if self.debug > 1:
self.browser.save_screenshot("debug1.png")
self.logger.log("Logging in...")
ele_usr = self.browser.find_element("name","username")
ele_pwd = self.browser.find_element("name","password")
ele_usr.send_keys(self.username)
ele_pwd.send_keys(self.password)
self.browser.find_element(By.ID , "clogs-captcha-button").click()
time.sleep(1)
#html = self.browser.page_source
#print (html)
if self.debug > 1:
time.sleep(1)
self.browser.save_screenshot("debug2.png")
def update_hosts(self):
count = 0
self.open_hosts_page()
time.sleep(1)
iteration = 1
next_renewal = []
self.browser.save_screenshot("test.png")
hosts = self.get_hosts()
for host in hosts:
host_link = self.get_host_link(host, iteration) # This is for if we wanted to modify our Host IP.
host_button = self.get_host_button(host, iteration) # This is the button to confirm our free host
host_name = host_link.text
expiration_days = self.get_host_expiration_days(host, iteration)
next_renewal.append(expiration_days)
self.logger.log(f"{host_name} expires in {str(expiration_days)} days")
if expiration_days < 7:
self.update_host(host_button, host_name)
count += 1
iteration += 1
self.browser.save_screenshot("results.png")
self.logger.log(f"Confirmed hosts: {count}", 2)
nr = min(next_renewal) - 6
today = date.today() + timedelta(days=nr)
day = str(today.day)
month = str(today.month + 1)
subprocess.call(['/usr/local/bin/noip-renew-skd.sh', day, month, "True"])
return True
def open_hosts_page(self):
self.logger.log(f"Opening {Robot.HOST_URL}...")
try:
self.browser.get(Robot.HOST_URL)
time.sleep(2)
#html = self.browser.page_source
#print (html)
except TimeoutException as e:
self.browser.save_screenshot("timeout.png")
self.logger.log(f"Timeout: {str(e)}")
def update_host(self, host_button, host_name):
self.logger.log(f"Updating {host_name}")
host_button.click()
time.sleep(3)
intervention = False
try:
if self.browser.find_elements(By.XPATH,"//h2[@class='big']")[0].text == "Upgrade Now":
intervention = True
except:
pass
if intervention:
raise Exception("Manual intervention required. Upgrade text detected.")
self.browser.save_screenshot(f"{host_name}_success.png")
@staticmethod
def get_host_expiration_days(host, iteration):
try:
host_remaining_days = host.find_element(By.XPATH,".//a[@class='no-link-style']").text
except:
host_remaining_days = "Expires in 0 days"
pass
regex_match = re.search("\\d+", host_remaining_days)
if regex_match is None:
raise Exception("Expiration days label does not match the expected pattern in iteration: {iteration}")
expiration_days = int(regex_match.group(0))
return expiration_days
@staticmethod
def get_host_link(host, iteration):
return host.find_element(By.XPATH ,".//a[@class='link-info cursor-pointer']")
@staticmethod
def get_host_button(host, iteration):
return host.find_element(By.XPATH ,".//following-sibling::td[4]/button[contains(@class, 'btn')]")
def get_hosts(self):
host_tds = self.browser.find_elements(By.XPATH, "//td[@class=\"word-break-col\"]")
self.browser.save_screenshot("end.png")
if len(host_tds) == 0:
raise Exception("No hosts or host table rows not found")
return host_tds
def run(self):
rc = 0
self.logger.log(f"Debug level: {self.debug}")
try:
self.login()
if not self.update_hosts():
rc = 3
except Exception as e:
self.logger.log(str(e))
self.browser.save_screenshot("exception.png")
subprocess.call(['/usr/local/bin/noip-renew-skd.sh', "*", "*", "False"])
rc = 2
finally:
self.browser.quit()
return rc
def main(argv=None): noip_username, noip_password, debug, = get_args_values(argv) return (Robot(noip_username, noip_password, debug)).run()
def get_args_values(argv):
if argv is None:
argv = sys.argv
if len(argv) < 3:
print(f"Usage: {argv[0]}
noip_username = argv[1]
noip_password = argv[2]
debug = 1
if len(argv) > 3:
debug = int(argv[3])
return noip_username, noip_password, debug
if name == "main": sys.exit(main())
Shoot me any questions, I will try to be faster!
Thanks for share your script, but get these error:
[2022/09/30 10:23:32] - Debug level: 2 [2022/09/30 10:23:32] - Opening https://www.noip.com/login... [2022/09/30 10:23:35] - Logging in... [2022/09/30 10:23:35] - 'WebDriver' object has no attribute 'find_element_by_name'