排版还需要好好整理一下

之前在windows10上写了一键启动的py脚本,现在需要部署到我的Linux服务器上

有考虑用systemd,但感觉流程有些复杂,要创建好几个文件

所以最终决定使用cron服务

实际使用操作的步骤

新建脚本文件dstTimedStart.py

nano ~/Dev/dstTimedStart.py

填写保存要执行的脚本

修改并规范后的代码

修改部分

  • 将重复功能封装到函数中

  • 增加重启失败循环重启功能

import time
import logging
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
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from selenium.webdriver.chrome.options import Options
 
# 设置 Chrome 选项
chrome_options = Options()
#chrome_options.add_argument('--headless')  # 启用无头模式
#chrome_options.add_argument('--disable-gpu')  # 禁用GPU加速(某些系统上可能需要)
chrome_options.add_argument("--headless")  # 启用无头模式
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--disable-gpu")
 
# 显式指定 Chrome 的路径
# chrome_options.binary_location = "/usr/bin/google-chrome"
# 配置日志记录
logging.basicConfig(filename='/root/Dev/log.txt', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
 
# 启动浏览器
driver = webdriver.Chrome( options=chrome_options)
 
try:
    # 访问登录页面
    driver.get("http://dstyun.cn/login")
    logging.info("******访问登录页面******")
 
    # 等待输入框出现
    WebDriverWait(driver, 10).until(
        EC.presence_of_all_elements_located((By.CLASS_NAME, "el-input__inner"))
    )
    logging.info("输入框已找到")
 
    # 获取所有 class 为 "el-input__inner" 的元素
    input_elements = driver.find_elements(By.CLASS_NAME, "el-input__inner")
 
    # 假设第一个元素是用户名输入框,第二个元素是密码输入框
    username_input = input_elements[0]
    password_input = input_elements[1]
 
    # 输入用户名和密码
    username_input.send_keys("room114514")
    password_input.send_keys("1919180")
    logging.info("用户名和密码已输入")
 
    # 等待登录按钮出现并点击
    login_button = WebDriverWait(driver, 5).until(
        EC.element_to_be_clickable((By.XPATH, "//button[contains(@class, 'el-button') and contains(@class, 'el-button--primary') and contains(@class, 'el-button--medium')]"))
    )
    login_button.click()
    logging.info("登录按钮已点击")
 
    # 等待页面加载完成,确保登录成功
    WebDriverWait(driver, 10).until(
        EC.url_changes("http://dstyun.cn/login")  # 假设登录成功后 URL 会变化
    )
    logging.info("登录成功,URL 已变化")
 
    # 获取当前页面的所有 Cookie
    cookies = driver.get_cookies()
    logging.info("获取到的 Cookie: %s", cookies)
 
    # 等待状态元素出现
    try:
        WebDriverWait(driver, 10).until(  # 增加超时时间
            EC.presence_of_all_elements_located((By.XPATH, "//div[@class='el-col el-col-24 el-col-xs-12 el-col-sm-12 el-col-md-12 el-col-lg-10 el-col-xl-8 myline']"))
        )
        logging.info("状态元素已找到01")
    except TimeoutException:
        logging.warning("状态元素未在规定时间内出现01")
 
    # 等待状态元素出现
    try:
        status_elements = WebDriverWait(driver, 10).until(  # 增加超时时间
            EC.presence_of_all_elements_located((By.XPATH, "//div[@class='el-col el-col-24 el-col-xs-6 el-col-sm-6 el-col-md-4 el-col-lg-4 el-col-xl-4 myline']"))
        )
        logging.info("状态元素已找到02")
    except TimeoutException:
        logging.warning("状态元素未在规定时间内出现02")
        raise
 
    # 检查状态元素的文本内容
    status_texts = [element.text for element in status_elements]
    logging.info("状态文本: %s", status_texts)
 
    # 检查是否所有状态都是“已开启”,三个状态 已关闭,加载中,已开启
    all_opened = all(text != "已关闭" for text in status_texts)
 
    if not all_opened:
        # 等待重启按钮出现并点击
        try:
            restart_button = WebDriverWait(driver, 10).until(  # 增加超时时间
                EC.element_to_be_clickable((By.XPATH, "//button[.//span[text()='一键重启']]"))
            )
            restart_button.click()
            logging.info("一键重启按钮已点击")
            time.sleep(30) #为了稳定点,改为20s
            
            # 检测重启后状态
            try:
                status_elements = WebDriverWait(driver, 10).until(  # 增加超时时间
                    EC.presence_of_all_elements_located((By.XPATH, "//div[@class='el-col el-col-24 el-col-xs-6 el-col-sm-6 el-col-md-4 el-col-lg-4 el-col-xl-4 myline']"))
                )
                logging.info("重启后状态元素已找到")
            except TimeoutException:
                logging.warning("重启后状态元素未在规定时间内出现")
                raise
 
            # 检查状态元素的文本内容
            status_texts = [element.text for element in status_elements]
            logging.info("重启后状态文本: %s", status_texts)
 
        except TimeoutException:
            logging.warning("重启按钮未在规定时间内出现")
        except NoSuchElementException:
            logging.warning("未找到重启按钮")
    else:
        logging.info("所有状态均已开启,无需重启")
 
finally:
    # 关闭浏览器
    driver.quit()
    logging.info("浏览器已关闭")

前一个版本

import time
import logging
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
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from selenium.webdriver.chrome.options import Options

# 设置 Chrome 选项
chrome_options = Options()
#chrome_options.add_argument('--headless')  # 启用无头模式
#chrome_options.add_argument('--disable-gpu')  # 禁用GPU加速(某些系统上可能需要)
chrome_options.add_argument("--headless")  # 启用无头模式
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--disable-gpu")

# 显式指定 Chrome 的路径
# chrome_options.binary_location = "/usr/bin/google-chrome"
# 配置日志记录
logging.basicConfig(filename='/root/Dev/log.txt', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# 启动浏览器
driver = webdriver.Chrome( options=chrome_options)

try:
    # 访问登录页面
    driver.get("http://dstyun.cn/login")
    logging.info("******访问登录页面******")

    # 等待输入框出现
    WebDriverWait(driver, 10).until(
        EC.presence_of_all_elements_located((By.CLASS_NAME, "el-input__inner"))
    )
    logging.info("输入框已找到")

    # 获取所有 class 为 "el-input__inner" 的元素
    input_elements = driver.find_elements(By.CLASS_NAME, "el-input__inner")

    # 假设第一个元素是用户名输入框,第二个元素是密码输入框
    username_input = input_elements[0]
    password_input = input_elements[1]

    # 输入用户名和密码
    username_input.send_keys("room114514")
    password_input.send_keys("1919180")
    logging.info("用户名和密码已输入")

    # 等待登录按钮出现并点击
    login_button = WebDriverWait(driver, 5).until(
        EC.element_to_be_clickable((By.XPATH, "//button[contains(@class, 'el-button') and contains(@class, 'el-button--primary') and contains(@class, 'el-button--medium')]"))
    )
    login_button.click()
    logging.info("登录按钮已点击")

    # 等待页面加载完成,确保登录成功
    WebDriverWait(driver, 10).until(
        EC.url_changes("http://dstyun.cn/login")  # 假设登录成功后 URL 会变化
    )
    logging.info("登录成功,URL 已变化")

    # 获取当前页面的所有 Cookie
    cookies = driver.get_cookies()
    logging.info("获取到的 Cookie: %s", cookies)

    # 等待状态元素出现
    try:
        WebDriverWait(driver, 5).until(  # 增加超时时间
            EC.presence_of_all_elements_located((By.XPATH, "//div[@class='el-col el-col-24 el-col-xs-12 el-col-sm-12 el-col-md-12 el-col-lg-10 el-col-xl-8 myline']"))
        )
        logging.info("状态元素已找到")
    except TimeoutException:
        logging.warning("状态元素未在规定时间内出现")

    # 等待状态元素出现
    try:
        status_elements = WebDriverWait(driver, 5).until(  # 增加超时时间
            EC.presence_of_all_elements_located((By.XPATH, "//div[@class='el-col el-col-24 el-col-xs-6 el-col-sm-6 el-col-md-4 el-col-lg-4 el-col-xl-4 myline']"))
        )
        logging.info("状态元素已找到")
    except TimeoutException:
        logging.warning("状态元素未在规定时间内出现")
        raise

    # 检查状态元素的文本内容
    status_texts = [element.text for element in status_elements]
    logging.info("状态文本: %s", status_texts)

    # 检查是否所有状态都是“已开启”,三个状态 已关闭,加载中,已开启
    all_opened = all(text != "已关闭" for text in status_texts)

    if not all_opened:
        # 等待重启按钮出现并点击
        try:
            restart_button = WebDriverWait(driver, 5).until(  # 增加超时时间
                EC.element_to_be_clickable((By.XPATH, "//button[.//span[text()='一键重启']]"))
            )
            restart_button.click()
            logging.info("一键重启按钮已点击")
            time.sleep(20) #为了稳定点,改为20s
            
            # 检测重启后状态
            try:
                status_elements = WebDriverWait(driver, 5).until(  # 增加超时时间
                    EC.presence_of_all_elements_located((By.XPATH, "//div[@class='el-col el-col-24 el-col-xs-6 el-col-sm-6 el-col-md-4 el-col-lg-4 el-col-xl-4 myline']"))
                )
                logging.info("重启后状态元素已找到")
            except TimeoutException:
                logging.warning("重启后状态元素未在规定时间内出现")
                raise

            # 检查状态元素的文本内容
            status_texts = [element.text for element in status_elements]
            logging.info("重启后状态文本: %s", status_texts)

        except TimeoutException:
            logging.warning("重启按钮未在规定时间内出现")
        except NoSuchElementException:
            logging.warning("未找到重启按钮")
    else:
        logging.info("所有状态均已开启,无需重启")

finally:
    # 关闭浏览器
    driver.quit()
    logging.info("浏览器已关闭")

修复BUG

抓虫,下面有问题,生成的log.txt不会在同级目录下,而是在root目录下,log.txt应该改成绝对路径

logging.basicConfig(filename='log.txt', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

改为

logging.basicConfig(filename='/root/Dev/log.txt', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

import time
import logging
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
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from selenium.webdriver.chrome.options import Options

# 设置 Chrome 选项
chrome_options = Options()
chrome_options.add_argument('--headless')  # 启用无头模式
chrome_options.add_argument('--disable-gpu')  # 禁用GPU加速(某些系统上可能需要)

# 配置日志记录
logging.basicConfig(filename='log.txt', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# 启动浏览器
driver = webdriver.Chrome(options=chrome_options)

try:
    # 访问登录页面
    driver.get("http://dstyun.cn/login")
    logging.info("访问登录页面")

    # 等待输入框出现
    WebDriverWait(driver, 10).until(
        EC.presence_of_all_elements_located((By.CLASS_NAME, "el-input__inner"))
    )
    logging.info("输入框已找到")

    # 获取所有 class 为 "el-input__inner" 的元素
    input_elements = driver.find_elements(By.CLASS_NAME, "el-input__inner")

    # 假设第一个元素是用户名输入框,第二个元素是密码输入框
    username_input = input_elements[0]
    password_input = input_elements[1]

    # 输入用户名和密码
    username_input.send_keys("room114514")
    password_input.send_keys("1919180")
    logging.info("用户名和密码已输入")

    # 等待登录按钮出现并点击
    login_button = WebDriverWait(driver, 5).until(
        EC.element_to_be_clickable((By.XPATH, "//button[contains(@class, 'el-button') and contains(@class, 'el-button--primary') and contains(@class, 'el-button--medium')]"))
    )
    login_button.click()
    logging.info("登录按钮已点击")

    # 等待页面加载完成,确保登录成功
    WebDriverWait(driver, 10).until(
        EC.url_changes("http://dstyun.cn/login")  # 假设登录成功后 URL 会变化
    )
    logging.info("登录成功,URL 已变化")

    # 获取当前页面的所有 Cookie
    cookies = driver.get_cookies()
    logging.info("获取到的 Cookie: %s", cookies)

    # 等待状态元素出现
    try:
        WebDriverWait(driver, 5).until(  # 增加超时时间
            EC.presence_of_all_elements_located((By.XPATH, "//div[@class='el-col el-col-24 el-col-xs-12 el-col-sm-12 el-col-md-12 el-col-lg-10 el-col-xl-8 myline']"))
        )
        logging.info("状态元素已找到")
    except TimeoutException:
        logging.warning("状态元素未在规定时间内出现")

    # 等待状态元素出现
    try:
        status_elements = WebDriverWait(driver, 5).until(  # 增加超时时间
            EC.presence_of_all_elements_located((By.XPATH, "//div[@class='el-col el-col-24 el-col-xs-6 el-col-sm-6 el-col-md-4 el-col-lg-4 el-col-xl-4 myline']"))
        )
        logging.info("状态元素已找到")
    except TimeoutException:
        logging.warning("状态元素未在规定时间内出现")
        raise

    # 检查状态元素的文本内容
    status_texts = [element.text for element in status_elements]
    logging.info("状态文本: %s", status_texts)

    # 检查是否所有状态都是“已开启”,三个状态 已关闭,加载中,已开启
    all_opened = all(text != "已关闭" for text in status_texts)

    if not all_opened:
        # 等待重启按钮出现并点击
        try:
            restart_button = WebDriverWait(driver, 5).until(  # 增加超时时间
                EC.element_to_be_clickable((By.XPATH, "//button[.//span[text()='一键重启']]"))
            )
            restart_button.click()
            logging.info("一键重启按钮已点击")
            time.sleep(10)
            
            # 检测重启后状态
            try:
                status_elements = WebDriverWait(driver, 5).until(  # 增加超时时间
                    EC.presence_of_all_elements_located((By.XPATH, "//div[@class='el-col el-col-24 el-col-xs-6 el-col-sm-6 el-col-md-4 el-col-lg-4 el-col-xl-4 myline']"))
                )
                logging.info("重启后状态元素已找到")
            except TimeoutException:
                logging.warning("重启后状态元素未在规定时间内出现")
                raise

            # 检查状态元素的文本内容
            status_texts = [element.text for element in status_elements]
            logging.info("重启后状态文本: %s", status_texts)

        except TimeoutException:
            logging.warning("重启按钮未在规定时间内出现")
        except NoSuchElementException:
            logging.warning("未找到重启按钮")
    else:
        logging.info("所有状态均已开启,无需重启")

finally:
    # 关闭浏览器
    driver.quit()
    logging.info("浏览器已关闭")

确保 dstTimedStart.py 脚本具有可执行权限。给脚本赋予权限

chmod +x ~/Dev/dstTimedStart.py

配置cron服务

确保 cron 服务正在运行。你可以使用以下命令来检查 cron 服务的状态:

sudo systemctl status cron

编辑 Crontab 文件

crontab -e

每天早上6:31启动~/Dev路径下的dstTimedStart.py,在文件末尾添加:

31 6 * * * /usr/bin/python3 ~/Dev/dstTimedStart.py

为了方便了解每次的启动情况,使用可以将脚本的输出重定向到文件来捕获任何错误信息或输出,这有助于调试问题。

31 6 * * * /usr/bin/python3 ~/Dev/dstTimedStart.py >> ~/Dev/dstTimedStart.log 2>&1

py脚本中使用了log,通常查看同级目录下的log.txt来判断启动过程更多一些

环境安装

selenium库

由于脚本中使用了selenium模块,未安装的需要安装

sudo pip3 install selenium

pip包管理

未安装pip的安装pip

sudo apt-get update
sudo apt-get install python3-pip

安装完成后,您可以通过运行 Python 并尝试导入 selenium 来验证它是否已正确安装:

python3 -c "import selenium; print(selenium.__version__)"

Google Chrome

安装Google Chrome

下载并安装Google Chrome

使用wget命令从Google的官方服务器下载Chrome的Debian安装包,然后使用dpkg命令进行安装。如果安装过程中出现依赖问题,可以使用apt-get命令来修复。

wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo dpkg -i google-chrome-stable_current_amd64.deb
sudo apt-get install -f  # 修复依赖问题
sudo dpkg -i google-chrome-stable_current_amd64.deb

ChromeDriver

安装ChromeDriver

确定Chrome版本

ChromeDriver 的版本需要与安装的 Google Chrome 版本匹配。因此,首先检查已安装的 Google Chrome 版本:

google-chrome --version

root@RainYun-vUQMSsZ0:~/Dev# google-chrome --version
Google Chrome 131.0.6778.204

参考教程:https://blog.csdn.net/qq_46315152/article/details/143290193

【链接】最新版本下载链接:Chrome for Testing availability

              版本114及以下下载链接:https://chromedriver.storage.googleapis.com/index.html

下载ChromeDriver

wget https://storage.googleapis.com/chrome-for-testing-public/131.0.6778.204/linux64/chromedriver-linux64.zip

解压并安装ChromeDriver

使用unzip命令解压下载的ChromeDriver压缩包,并将其移动到系统的可执行路径中(如/usr/local/bin/)。然后,给ChromeDriver赋予可执行权限。

unzip chromedriver-linux64.zip chromedriver
cd chromedriver-linux64
sudo mv chromedriver /usr/local/bin/
sudo chmod +x /usr/local/bin/chromedriver

删除已经无用的chromedriver-linux64

rm -rf chromedriver-linux64

在Linux系统中,包括Debian,tar命令本身并不直接支持解压zip格式的文件。tar命令主要用于处理.tar、.tar.gz、.tar.bz2等格式的压缩文件。

要解压zip文件,应使用unzip命令。以下是使用unzip命令解压zip文件的步骤:

验证 ChromeDriver 是否安装成功,运行以下命令:

chromedriver --version

root@RainYun-vUQMSsZ0:~/Dev/chromedriver-linux64# chromedriver --version
ChromeDriver 131.0.6778.204 (52*****56f9b7853******0-refs/branch-heads/6778_155@{#7})

unzip工具

安装unzip工具

sudo apt-get update
sudo apt-get install unzip

BUG修复

DevTools listening on ws://127.0.0.1:16225/devtools/browser/e**2-d**2-4**f-8*5-58******123
[15872:11480:1227/022035.023:ERROR:ssl_client_socket_impl.cc(878)] handshake failed; returned -1, SSL error code 1, net_error -100

执行的时候会有报错,起初以为因为ssl协议的问题,但是加了头,没用

# --ignore-certificate-errors
# 此参数告诉Chrome浏览器在访问HTTPS网站时忽略SSL证书错误。
# 这意味着即使网站的SSL证书存在问题(如过期、不被信任等),
# 浏览器也不会显示警告信息,而是继续加载页面。
# 注意:在生产环境中使用此参数会降低安全性。
chrome_options.add_argument('--ignore-certificate-errors')
# --allow-insecure-localhost
# 此参数允许Chrome浏览器在localhost或127.0.0.1上加载具有不安全证书(如自签名证书)的HTTPS页面。
# 这通常用于开发环境,其中开发者可能需要在本地机器上测试HTTPS功能。
# 注意:同样,在生产环境中使用此参数也会降低安全性。
chrome_options.add_argument('--allow-insecure-localhost')

后来发现可能是网站所有者添加了一点小料针对自动脚本,检测点击完一键启动后若瞬间关闭页面就启动失败,所以使用time.sleep(10)就能解决,本次错误排查花费了将近3h

加个头文件

import time

在点击一键重启按钮后无条件等待10s

logging.info("一键重启按钮已点击")
time.sleep(10)

笼统的安装步骤

安装cron服务

通常,Debian 系统默认已经安装了 cron 服务。如果未安装,可以通过以下命令进行安装:

sudo apt-get update
sudo apt-get install cron

编辑 Crontab 文件

crontab -e

如果是第一次运行,系统可能会要求你选择一个文本编辑器(如 nano 或 vim)。

这里我习惯用nano,所以输入1,回车。

添加定时任务

在打开的 crontab 文件中,按照以下格式添加定时任务:

* * * * * command_to_execute

每个字段的含义如下:

  • 第一个 * 代表分钟(0-59)

  • 第二个 * 代表小时(0-23)

  • 第三个 * 代表一个月中的第几天(1-31)

  • 第四个 * 代表月份(1-12)

  • 第五个 * 代表星期几(0-7,0 和 7 都代表星期日)

command_to_execute 是你想要定时执行的命令或脚本。例如,如果你想每天凌晨 2 点执行 dstTimedStart.py 脚本,可以添加以下行:

0 2 * * * /usr/bin/python3 /path/to/your/dstTimedStart.py

注意:确保 /usr/bin/python3 是你系统中 Python 3 的正确路径,/path/to/your/dstTimedStart.py 是你的脚本路径。

保存并退出编辑器

根据你选择的编辑器,保存并退出。在 nano 中,你可以按 Ctrl+O 保存,然后按 Ctrl+X 退出。在 vim 中,你可以按 :wq 保存并退出。

验证 Cron 任务

你可以通过以下命令查看当前用户的 crontab 任务,确保你的定时任务已经成功添加:

crontab -l

此外,为了确保定时任务正常工作,你可以在添加任务后稍等片刻(比如等待几分钟),然后手动触发一次 cron 任务来测试它是否正常工作。

注意事项

  • 定时任务可能会导致未保存的数据丢失,因此在设置定时任务之前,请确保你的工作环境能够处理这种情况,并提前保存所有重要数据。

  • 如果你的脚本需要特定的工作目录或环境变量,请在 crontab 文件中使用 cd 命令或设置相应的环境变量。

  • 你可以使用 >>> 将脚本的输出重定向到文件,以便稍后查看。

通过以上步骤,你就可以在 Debian 系统上使用 cron 服务来定时启动 dstTimedStart.py 脚本了。

参考

【超详细】手把手教你,ChromeDriver下载与安装_chromedriver安装-CSDN博客