本次实战实现目标如下:
目录
1.抓取网页信息,获取对应内容
get_daily_sentence.py
python
import requests
from lxml import etree
def get_daily_sentence():
url = 'https://dict.eudic.net/home/dailysentence/'
try:
# 发送请求
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
r = requests.get(url, headers=headers)
r.raise_for_status() # 检查请求是否成功
# 解析 HTML
html = etree.HTML(r.text)
# 提取内容
en_sentence = html.xpath('/html/body/div/div[2]/div[1]/div[2]/p[1]/text()')
zh_translation = html.xpath('/html/body/div/div[2]/div[1]/div[2]/p[2]/text()')
# 打印结果
# if en_sentence and zh_translation:
# print("=" * 50)
# print("每日一句")
# print("=" * 50)
# print(f"英文: {en_sentence[0]}")
# print(f"中文: {zh_translation[0]}")
# print("=" * 50)
# else:
# print("未找到每日一句内容,可能是XPath路径有变化")
print(f"英文: {en_sentence[0]}")
print(f"中文: {zh_translation[0]}")
except requests.RequestException as e:
print(f"请求出错: {e}")
except Exception as e:
print(f"处理出错: {e}")
if __name__ == "__main__":
get_daily_sentence()
2.启用日志输出,实现信息记录
python
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('x:\\xx\\scheduler.log', encoding='utf-8'),
logging.StreamHandler()
]
)
3.通过配置文件,实现脚本调用
4.完成qq邮箱发送自定义信息
(动态获取通过api文本信息)
python
# """
# @Project :test
# @File :1029.py
# @IDE :PyCharm
# @Author :by202
# @Date :2025/10/29 11:16
# """
import requests
from lxml import etree
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
url = 'https://dict.eudic.net/home/dailysentence/'
r = requests.get(url)
text = r.text
html = etree.HTML(text)
# enx = text.xpath('/html/body/div/div[2]/div[1]/div[2]/p[1]/text()')
en = html.xpath('/html/body/div/div[2]/div[1]/div[2]/p[1]/text()')
zh = html.xpath('/html/body/div/div[2]/div[1]/div[2]/p[2]/text()')
text = en[0] +"\n"+ zh[0]
print(text)
print(f"英文: {en[0]}")
print(f"中文: {zh[0]}")
# 通过qq邮箱进行发送
my_sender = '2@qq.com' # 填写发信人的邮箱账号
my_pass = 'yjyqvdgea' # 发件人邮箱授权码
my_user = '5@qq.com' # 收件人邮箱账号
su_user = '1@qq.com' #抄送多人发送,在下面的sendmail方法中进行抄送即可
def mail():
ret = True
try:
msg = MIMEText(text, 'plain', 'utf-8') # 填写邮件内容
# msg = MIMEText(zh[0], 'plain', 'utf-8') # 填写邮件内容
msg['From'] = formataddr(["tracy", my_sender]) # 括号里的对应发件人邮箱昵称、发件人邮箱账号
msg['To'] = formataddr(["test", my_user]) # 括号里的对应收件人邮箱昵称、收件人邮箱账号
msg['Subject'] = "发送邮件测试" # 邮件的主题,也可以说是标题
server = smtplib.SMTP_SSL("smtp.qq.com", 465) # 发件人邮箱中的SMTP服务器
server.login(my_sender, my_pass) # 括号中对应的是发件人邮箱账号、邮箱授权码
server.sendmail(my_sender, [my_user,su_user ], msg.as_string()) # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
# server.sendmail(my_sender, [su_user, ], msg.as_string()) wu
server.quit() # 关闭连接
except Exception: # 如果 try 中的语句没有执行,则会执行下面的 ret=False
ret = False
return ret
ret = mail()
if ret:
print("邮件发送成功")
else:
print("邮件发送失败")
5.实现热重启功能
修改配置文件不需重启脚本
task_config.json
javascript
{
"tasks": [
{
"name": "发送邮件",
"script_path": "C:\\test\\send_mail.py",
"schedule": "00:00",
"enabled": true
},
{
"name": "发送邮件",
"script_path": "E:\\test\\send_mail.py",
"schedule": "14:52",
"enabled": true
}
]
}
python
import schedule
import time
import subprocess
import json
import logging
from datetime import datetime
import os
import threading
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('C:\\scripts\\scheduler.log', encoding='utf-8'),
logging.StreamHandler()
]
)
class TaskScheduler:
def __init__(self, config_file):
self.config_file = config_file
self.tasks = self.load_config()
def load_config(self):
"""加载任务配置"""
try:
with open(self.config_file, 'r', encoding='utf-8') as f:
return json.load(f)['tasks']
except Exception as e:
logging.error(f"加载配置文件失败: {e}")
return []
def run_script(self, script_path, task_name):
"""运行Python脚本 - 修复编码问题"""
try:
logging.info(f"开始执行任务: {task_name}")
# 检查脚本文件是否存在
if not os.path.exists(script_path):
logging.error(f"脚本文件不存在: {script_path}")
return
# 设置环境变量,指定UTF-8编码
env = os.environ.copy()
env['PYTHONIOENCODING'] = 'utf-8'
env['PYTHONUTF8'] = '1'
# 使用subprocess运行脚本,指定编码
result = subprocess.run(
['python', script_path],
capture_output=True,
text=True,
timeout=300, # 5分钟超时
encoding='utf-8',
errors='ignore', # 忽略编码错误
env=env
)
if result.returncode == 0:
logging.info(f"任务完成: {task_name}")
if result.stdout and result.stdout.strip():
# 限制输出长度,避免日志过大
output = result.stdout.strip()
if len(output) > 500:
output = output[:500] + "...(输出过长,已截断)"
logging.info(f"任务输出: {output}")
else:
logging.error(f"任务失败: {task_name}, 返回码: {result.returncode}")
if result.stderr and result.stderr.strip():
error_output = result.stderr.strip()
if len(error_output) > 500:
error_output = error_output[:500] + "...(错误信息过长,已截断)"
logging.error(f"错误信息: {error_output}")
except subprocess.TimeoutExpired:
logging.error(f"任务超时: {task_name}")
except FileNotFoundError:
logging.error(f"Python解释器或脚本文件未找到: {script_path}")
except Exception as e:
logging.error(f"执行任务异常 {task_name}: {str(e)}")
def run_script_safe(self, script_path, task_name):
"""安全运行脚本 - 在新线程中运行避免阻塞主线程"""
def run_in_thread():
self.run_script(script_path, task_name)
thread = threading.Thread(target=run_in_thread, name=f"Task-{task_name}")
thread.daemon = True # 设置为守护线程
thread.start()
def setup_schedule(self):
"""设置定时任务"""
for task in self.tasks:
if not task['enabled']:
continue
script_path = task['script_path']
task_name = task['name']
schedule_time = task['schedule']
# 检查脚本是否存在
if not os.path.exists(script_path):
logging.error(f"脚本文件不存在,跳过任务: {task_name} - {script_path}")
continue
# 每天固定时间执行
schedule.every().day.at(schedule_time).do(
self.run_script_safe, script_path, task_name
)
logging.info(f"已安排任务: {task_name} - 每天 {schedule_time}")
def run(self):
"""运行调度器"""
logging.info("任务调度器启动...")
self.setup_schedule()
logging.info("调度器运行中,按 Ctrl+C 退出...")
while True:
try:
schedule.run_pending()
time.sleep(30) # 每30秒检查一次,减少CPU使用
except KeyboardInterrupt:
logging.info("调度器被用户中断")
break
except Exception as e:
logging.error(f"调度器运行异常: {e}")
time.sleep(60)
if __name__ == "__main__":
scheduler = TaskScheduler("task_config.json")
scheduler.run()
6.部署到WinServer2012云服务器
每日指定时间运行对应脚本
(winserver/centos,理论上主调度文件可通用)
效果6:


7.部署到Linux云服务器
使用crontab -e每日指定时间运行对应脚本
效果7.
在centos系统上进行测试
可以安装好python后进行虚拟环境创建
pip install requests,bs4,schedule......
更新-2025年11月13日

python
# -*- coding: utf-8 -*-
import smtplib
import sys
import io
import requests
from lxml import etree
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import formataddr
from datetime import datetime
# 设置标准输出编码为UTF-8
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
my_sender = '@qq.com' # 填写发信人的邮箱账号
my_pass = 'a' # 发件人邮箱授权码
my_user = '@qq.com' # 收件人邮箱账号
jie = '@qq.com'
def get_daily_sentence():
"""获取每日英语句子"""
try:
url = 'https://dict.eudic.net/home/dailysentence/'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
r = requests.get(url, headers=headers, timeout=10)
r.encoding = 'utf-8'
text = r.text
html = etree.HTML(text)
# 提取英文和中文句子
en = html.xpath('/html/body/div/div[2]/div[1]/div[2]/p[1]/text()')
zh = html.xpath('/html/body/div/div[2]/div[1]/div[2]/p[2]/text()')
if en and zh:
english_sentence = en[0].strip()
chinese_sentence = zh[0].strip()
return english_sentence, chinese_sentence
else:
return "No sentence found today.", "今日未找到句子。"
except Exception as e:
print(f"获取每日句子失败: {e}")
return "Failed to get sentence.", "获取句子失败。"
def send_mail():
ret = True
try:
# 获取每日句子
english, chinese = get_daily_sentence()
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 创建邮件对象
msg = MIMEMultipart('related')
msg['From'] = formataddr(["每日英语", my_sender])
msg['To'] = formataddr(["收件人", my_user,])
msg['Subject'] = f"每日英语学习 {datetime.now().strftime('%Y-%m-%d')}"
# 创建HTML内容
html_content = f"""
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body {{
font-family: 'Microsoft YaHei', Arial, sans-serif;
margin: 0;
padding: 0;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
}}
.container {{
max-width: 600px;
margin: 0 auto;
background: white;
border-radius: 20px;
overflow: hidden;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
margin-top: 20px;
margin-bottom: 20px;
}}
.header {{
background: linear-gradient(135deg, #ff6b6b 0%, #feca57 100%);
color: white;
padding: 40px 30px;
text-align: center;
}}
.content {{
padding: 40px 30px;
}}
.sentence-en {{
font-size: 24px;
font-weight: bold;
color: #2c3e50;
line-height: 1.6;
text-align: center;
margin-bottom: 20px;
font-style: italic;
}}
.sentence-zh {{
font-size: 18px;
color: #7f8c8d;
line-height: 1.6;
text-align: center;
margin-bottom: 30px;
}}
.image-section {{
text-align: center;
margin: 30px 0;
padding: 20px;
background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
border-radius: 15px;
}}
.footer {{
text-align: center;
padding: 20px;
background: #34495e;
color: #bdc3c7;
font-size: 12px;
}}
.date {{
background: rgba(255,255,255,0.2);
display: inline-block;
padding: 8px 20px;
border-radius: 20px;
margin-top: 10px;
font-size: 14px;
}}
.emoji {{
font-size: 48px;
margin-bottom: 20px;
}}
</style>
</head>
<body>
<div class="container">
<div class="header">
<div class="emoji">📚</div>
<h1 style="margin:0; font-size: 32px;">每日英语学习</h1>
<div class="date">{current_time}</div>
</div>
<div class="content">
<div class="sentence-en">
"{english}"
</div>
<div class="sentence-zh">
{chinese}
</div>
<div class="image-section">
<h3 style="color: #333; margin-bottom: 20px;">🎉 坚持学习,每天进步!</h3>
<img src="https://staticv2.hi2future.com/upload/emotion/tsj/t_0034.gif"
alt="Learning GIF"
style="max-width: 200px; border-radius: 15px; border: 4px solid white; box-shadow: 0 8px 25px rgba(0,0,0,0.15);">
<p style="margin-top: 15px; color: #666; font-size: 14px;">每天一句英语,积累无限可能</p>
</div>
</div>
<div class="footer">
<p>📧 邮件为每日15点内时间段自动发出,来自九牧</p>
<p>🔔 如需拒收可联系发件人,或者拉入黑名单</p>
<p style="margin-top: 10px; opacity: 0.7;">© {datetime.now().strftime('%Y')} 每日多邻国英语学习计划</p>
</div>
</div>
</body>
</html>
"""
# 纯文本版本(备用)
text_content = f"""
每日英语 - {datetime.now().strftime('%Y-%m-%d')}
英文句子:
{english}
中文翻译:
{chinese}
{'-' * 50}
邮件为每日15点自动发出,来自九牧
如需拒收可联系发件人,或者拉入黑名单
"""
# 添加HTML内容
msg.attach(MIMEText(html_content, 'html', 'utf-8'))
# 添加纯文本内容(某些邮箱客户端可能不支持HTML时显示)
msg.attach(MIMEText(text_content, 'plain', 'utf-8'))
# 发送邮件
server = smtplib.SMTP_SSL("smtp.qq.com", 465)
server.login(my_sender, my_pass)
server.sendmail(my_sender, [my_user,jie ], msg.as_string())
server.quit()
print(f"每日英语邮件发送成功 - {current_time}")
print(f"英文: {english}")
print(f"中文: {chinese}")
return True
except Exception as e:
error_msg = f"邮件发送失败 - 错误信息: {str(e)}"
print(error_msg)
return False
if __name__ == "__main__":
try:
success = send_mail()
sys.exit(0 if success else 1)
except Exception as e:
print(f"脚本执行异常: {str(e)}")
sys.exit(1)

