批处理文件未在任务调度程序中运行 python 脚本

dav*_*ork 1 python firefox batch-file taskscheduler

我有一个抓取python 脚本和一个批处理文件,当从 CMD 运行时可以完美运行,但是当我尝试从任务计划程序运行它时没有任何反应。

我知道有很多关于同一问题的问题,但我已经尝试了所有建议的答案,但似乎没有一个可行。

不知道这是否相关,但脚本会打开 Firefox 并抓取一些网站。

已尝试为我正在使用的文件夹和文件添加完全权限。此外,尝试在任务计划程序中设置“无论用户是否登录都运行”、“以最高权限运行”、“启动(可选):添加/批处理/文件/路径”等

批处理文件:

py "C:\python_test\myscript.py"
Run Code Online (Sandbox Code Playgroud)

它应该运行 python 脚本,它打开 Firefox 并抓取一些网站,获取它们的链接并将它们保存在一个 csv 文件中

这是 myscript.py:

import datetime
import time
import csv
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
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
import os

file_path = r"C:\General\{0:%Y%m%d}\results{0:%Y%m%d%H%M%S}.csv".format(datetime.datetime.now())
directory = os.path.dirname(file_path)

try:
    os.stat(directory)
except:
    os.mkdir(directory)

from bs4 import BeautifulSoup
 
 
def init_driver():
    caps = DesiredCapabilities.FIREFOX
    caps['marionette'] = True
    driver = webdriver.Firefox(capabilities=caps)
    driver.wait = WebDriverWait(driver, 15)
    return driver
 

xpath = {
    'english': '//*[@id="xxx"]',
    'soort': '//*[@id="xxx"]/option[text()=\'|- Announcement of change in denominator or in thresholds\']',
    'start': '//*[@id="xxx"]',
    'end': '//*[@id="xxx"]',
    'submit': '//*[@id="xxx"]',
    'pub_sort': '//*[@id="xxx"]',
}
 
if __name__ == "__main__":

    driver = init_driver()
    try:
        driver.get("http://SOMEWEBSITE") 
        driver.find_element_by_css_selector('[id$=hplEnglish]').click()
    except Exception:
        DoNothing = ""

    
    time.sleep(2)
    driver.find_element_by_css_selector('[id$=hplEnglish]').click()
    time.sleep(3)
    #alert_obj = driver.switch_to.alert
    #alert_obj.dismiss()
    #driver.find_element_by_xpath(xpath['english']).click()
    today = datetime.datetime.now()
    driver.wait.until(EC.element_to_be_clickable((By.XPATH, xpath['soort']))).click()
    driver.find_element_by_xpath(xpath['start']).send_keys((today-datetime.timedelta(weeks=1)).strftime('%d/%m/%Y'))
    driver.find_element_by_xpath(xpath['end']).send_keys(today.strftime('%d/%m/%Y'))
    driver.find_element_by_xpath(xpath['submit']).click()
    for i in range(2):
        driver.wait.until(EC.element_to_be_clickable((By.XPATH, xpath['pub_sort']))).click()
    time.sleep(5)
    html = driver.page_source
    driver.quit()
    
    results = BeautifulSoup(html, 'html.parser').find('div', { 'id': 'SearchResults'}).table
    res = [['issuer', 'type', 'date']]
    for x in results.find_all('tr')[1:]:
        # print(x.text.strip())
        try:
            a, b, c = [i.text.strip() for i in x.find_all('td', class_='resultItemTop')[:3]]
            res.append([a,b,c])
        except ValueError:
            continue

        
    with open(file_path, 'w', newline='') as result:
        writer = csv.writer(result, delimiter=',')
        writer.writerows(res)
        print('finished')

Run Code Online (Sandbox Code Playgroud)

Mof*_*ofi 5

介绍

我建议先阅读在将批处理文件作为计划任务执行时必须考虑什么?

问题 1:当前目录

这里的第一个问题很可能是运行批处理文件的当前目录。

双击批处理文件时,Windows 会将批处理文件的目录设置为当前目录,但批处理文件路径是以\\computername\share\.

计划任务的当前目录默认为%SystemRoot%\System32,即 Windows 系统目录,当然它是特别保护以防止修改的。许多批处理文件期望当前目录是批处理文件的目录,而不是任何其他目录。

解决方案1:在计划任务的属性中定义目录中的启动

  • 启动 Windows任务计划程序
  • 导航到任务并双击它以打开任务的属性
  • 选择选项卡Action并单击按钮Edit
  • Start in (optional)。在此处输入执行的批处理文件的路径。
  • 单击“确定”按钮两次以在属性中保存此重要修改。

解决方案 2:使用CD将批处理文件目录设为当前目录。

在第一行之后的批处理文件中插入通常@echo off是以下行:

cd /D "%~dp0"
Run Code Online (Sandbox Code Playgroud)

%SystemRoot%\System32只要不使用 UNC 路径启动批处理文件,此命令行就会将当前目录从默认目录更改为批处理文件的目录。

打开命令提示符窗口并cd /?在命令CD和选项上运行以获取帮助/D

解决方案 3:使用PUSHD将批处理文件目录设为当前目录。

如果批处理文件存储在使用 UNC 路径访问的网络资源上,并且计划任务配置为使用具有读取网络资源上批处理文件内容的权限的凭据(用户帐户和密码)运行,则此解决方案是最好的。

在第一行之后的批处理文件中插入通常是@echo off以下几行:

setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0"
Run Code Online (Sandbox Code Playgroud)

批处理文件还应包含在退出批处理文件处理这两行之前执行的最后两行:

popd
endlocal
Run Code Online (Sandbox Code Playgroud)

打开命令提示符窗口,然后运行pushd /?popd /?setlocal /?endlocal /?在这四个命令的帮助,也看到这个答案对于这四个命令的更多详细信息。

解决方案 4:将所有内容编码为独立于当前目录。

第四种解决方案是编写批处理文件和Python脚本,以便在批处理文件和Python脚本执行时独立于当前目录是哪个目录。

此解决方案要求使用完全限定的文件/文件夹名称指定所有文件和目录,这意味着完整路径 + 文件/文件夹名称 + 文件扩展名。

完整的文件/文件夹路径可以从执行时的已知路径派生,如批处理文件的路径,可以在批处理文件中引用,%~dp0并扩展为始终以反斜杠结尾的路径字符串,这意味着它可以与文件/文件夹连接名称而不使用额外的反斜杠。

另请参阅有关Windows 环境变量的Wikipedia 文章。

问题 2:环境变量

计划任务通常使用内置的本地系统帐户执行。因此,仅为用于开发和测试批处理文件的用户帐户定义的所有环境变量要么根本没有定义,要么定义不同。

打开从Windows控制面板从产品系统高级系统设置或按组合键Win+Break如果键盘有一个键Break(通常为交替功能需要按下另外的键Fn),并点击下一个高级系统设置在左侧。在系统属性中打开的对话框中机智选项卡高级选择含有在底部的按钮环境变量...必须点击打开环境变量窗口。

有两个环境变量列表:User variables for ...System variables。该系统变量的所有账户,包括内置的本地系统帐户定义。该用户变量仅用于显示用户定义。

为当前用户定义的用户变量很重要,这可能是当前用户双击执行的批处理文件有效的原因,但不能作为内置系统帐户的计划任务执行。一个用户 PATH通常是不工作的执行为计划任务的批处理文件,如果使用的脚本和可执行文件依赖于特定的文件夹路径中的一个主要来源本地 PATH定义用户 PATH

请查看“X 未被识别为内部或外部命令、可运行程序或批处理文件”的原因是什么?有关用于写入批处理文件而不是具有完全限定文件名的脚本/可执行文件的系统用户本地 PATH和环境变量的更多信息。PATHEXTpy

所以使用肯定更好

"C:\Python27\python.exe" "C:\python_test\myscript.py"
Run Code Online (Sandbox Code Playgroud)

而不是使用

py "C:\python_test\myscript.py"
Run Code Online (Sandbox Code Playgroud)

这在结果中cmd.exe搜索周围为一个文件py使用本地 PATHEXT本地 PATH环境变量如果包含文件的文件夹,其可以在文件py中定义用户 PATH

我还没有安装Python,所以不知道py真正是什么。它可能是一个带有文件名的批处理文件,py.cmd或者py.bat在这种情况下,如果批处理文件在命令行之后包含其他命令行,并且可能取决于用户环境变量,则必须使用命令CALL。它可能是Python安装文件夹中的符号链接。我不知道。pypython.exe

问题 3:网络资源

许多计划任务通过网络访问文件、文件夹或数据。在这种情况下,计划任务必须配置为使用凭据(用户帐户和密码)运行,该凭据具有访问网络资源上的文件、文件夹或数据所需的权限。在这种情况下,使用内置本地系统帐户几乎不是运行计划任务的正确选择,因为本地系统帐户通常没有权限读取/写入任何网络资源上的数据。

结论

在我看来,编写一个作为计划任务执行的批处理文件以尽可能独立于 Windows 任务计划程序本身执行的批处理文件中未定义的其他批处理文件和环境变量是一种很好的做法。依赖于其他脚本文件和定义在主脚本之外的变量的设计通常迟早(有时是几年后)会导致意外的执行问题。

为作为计划任务执行而编写的脚本的程序员应该非常清楚脚本和调用的可执行文件依赖于哪些文件、库、环境变量和注册表项/值才能正常工作。

仅包含一行以使用某些参数执行一个应用程序的批处理文件是完全没有必要的,并且只是由于要运行的可执行文件而导致计划任务无法正常工作的潜在来源,在这种情况下,它的参数也可以直接在计划任务的属性中设置. 绝对不需要%SystemRoot%\System32\cmd.exe使用隐式选项运行/C来处理仅包含一个命令行的指定批处理文件来执行具有零个或多个参数的应用程序,因为 Windows 任务调度程序也可以直接使用其参数运行应用程序。