1. 为什么需要办公看板自动化?
作为每天要处理大量重复性工作的职场人,我深刻理解手动处理OA流程的痛苦。记得刚入职时,我每天要花2小时手动检查各种审批状态、整理报表数据、发送提醒邮件。直到有一天漏看了一个加急审批,差点耽误项目进度,这才下定决心用Python改造工作流程。
现代办公看板通常集成了任务管理、审批流程、数据报表等功能,但缺乏智能化的主动提醒和自动化处理能力。通过Python,我们可以实现:
- 自动抓取OA系统数据并可视化展示
- 基于规则或AI模型的智能提醒
- 定时执行重复性数据处理任务
- 跨系统数据同步与整合
这个方案特别适合需要同时处理多个项目进度的PM、经常要汇总各部门数据的运营、以及需要监控大量审批流程的行政人员。接下来我会分享从零开始搭建这样一个系统的完整过程。
2. 环境准备与基础配置
2.1 Python环境搭建
推荐使用Python 3.8+版本,这个版本在稳定性和新特性之间取得了很好的平衡。我习惯用miniconda管理环境:
bash复制conda create -n oa_auto python=3.8
conda activate oa_auto
必须安装的核心库:
bash复制pip install pandas requests beautifulsoup4 selenium schedule python-dotenv
注意:如果OA系统是网页版,建议使用浏览器开发者工具(F12)先分析网络请求,确定是传统网页还是SPA应用。传统网页用requests+BeautifulSoup足够,SPA应用则需要Selenium控制浏览器。
2.2 连接OA系统的三种方式
根据不同的OA系统类型,连接方式也不同:
- API接口(最理想情况):
python复制import requests
headers = {'Authorization': 'Bearer your_token'}
response = requests.get('https://oa.example.com/api/tasks', headers=headers)
- 数据库直连(需要IT支持):
python复制import pyodbc
conn = pyodbc.connect('DRIVER={ODBC Driver};SERVER=oa_db;DATABASE=oa;UID=user;PWD=pass')
- 网页爬取(最后的选择):
python复制from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://oa.example.com/login')
driver.find_element_by_id('username').send_keys('your_user')
driver.find_element_by_id('password').send_keys('your_pass')
driver.find_element_by_id('login-btn').click()
2.3 配置文件管理
永远不要把敏感信息硬编码在脚本中!我推荐使用.env文件:
ini复制# .env文件示例
OA_URL=https://oa.example.com
OA_USER=your_username
OA_PASS=your_password
API_KEY=sk_test_123456
然后在Python中读取:
python复制from dotenv import load_dotenv
load_dotenv()
import os
url = os.getenv('OA_URL')
3. 核心功能实现
3.1 数据获取与解析
假设我们的OA系统提供了API接口,获取待办事项的典型代码:
python复制def fetch_tasks():
try:
response = requests.get(
f"{os.getenv('OA_URL')}/api/v1/tasks",
headers={'Authorization': f"Bearer {os.getenv('API_KEY')}"},
params={'status': 'pending'}
)
response.raise_for_status()
return response.json()['data']
except requests.exceptions.RequestException as e:
print(f"获取任务失败: {e}")
return []
对于返回的JSON数据,用pandas处理特别方便:
python复制import pandas as pd
def process_tasks(tasks):
df = pd.DataFrame(tasks)
# 计算每个项目的逾期情况
df['due_date'] = pd.to_datetime(df['due_date'])
df['is_overdue'] = df['due_date'] < pd.Timestamp.now()
return df
3.2 看板可视化
使用HTML+CSS生成可视化看板:
python复制def generate_dashboard(df):
overdue = df[df['is_overdue']]
urgent = df[df['priority'] == 'high']
html = f"""
<html>
<style>
.card {{ border: 1px solid #ddd; padding: 15px; margin: 10px; border-radius: 5px; }}
.overdue {{ background-color: #ffebee; }}
.urgent {{ background-color: #fff8e1; }}
</style>
<body>
<h1>OA工作看板 {pd.Timestamp.now().strftime('%Y-%m-%d %H:%M')}</h1>
<div class="card" style="background-color: #f5f5f5;">
<h3>统计概览</h3>
<p>总任务数: {len(df)}</p>
<p>逾期任务: {len(overdue)}</p>
<p>紧急任务: {len(urgent)}</p>
</div>
"""
for _, task in df.iterrows():
html += f"""
<div class="card {'overdue' if task['is_overdue'] else 'urgent' if task['priority'] == 'high' else ''}">
<h3>{task['title']}</h3>
<p>项目: {task['project']}</p>
<p>截止: {task['due_date'].strftime('%Y-%m-%d')}</p>
<p>负责人: {task['assignee']}</p>
</div>
"""
html += "</body></html>"
with open('dashboard.html', 'w') as f:
f.write(html)
3.3 AI提醒功能实现
使用OpenAI API实现智能提醒(需先安装openai库):
python复制import openai
def generate_reminder(task):
prompt = f"""
你是一个高效的办公助手,需要提醒用户处理以下任务:
标题:{task['title']}
项目:{task['project']}
截止时间:{task['due_date']}
当前状态:{'已逾期' if task['is_overdue'] else '即将到期'}
请生成一段友好但紧迫的提醒消息,不超过50字。
"""
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": prompt}],
max_tokens=100
)
return response.choices[0].message.content
发送邮件的完整示例:
python复制import smtplib
from email.mime.text import MIMEText
def send_email(to, subject, content):
msg = MIMEText(content, 'html')
msg['Subject'] = subject
msg['From'] = os.getenv('EMAIL_FROM')
msg['To'] = to
with smtplib.SMTP(os.getenv('SMTP_SERVER'), int(os.getenv('SMTP_PORT'))) as server:
server.starttls()
server.login(os.getenv('EMAIL_USER'), os.getenv('EMAIL_PASS'))
server.send_message(msg)
3.4 定时任务管理
使用schedule库实现定时任务:
python复制import schedule
import time
def job():
print(f"执行定时任务 {time.strftime('%Y-%m-%d %H:%M:%S')}")
tasks = fetch_tasks()
df = process_tasks(tasks)
generate_dashboard(df)
# 检查逾期任务
overdue = df[df['is_overdue']]
for _, task in overdue.iterrows():
reminder = generate_reminder(task)
send_email(task['assignee_email'], f"任务逾期提醒: {task['title']}", reminder)
# 每天9点和16点各执行一次
schedule.every().day.at("09:00").do(job)
schedule.every().day.at("16:00").do(job)
while True:
schedule.run_pending()
time.sleep(60)
更高级的定时任务可以使用APScheduler:
python复制from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler()
@sched.scheduled_job('cron', hour='9,16', minute='0')
def scheduled_job():
job()
sched.start()
4. 进阶功能与优化
4.1 异常处理与重试机制
网络请求难免会失败,完善的异常处理很重要:
python复制from tenacity import retry, stop_after_attempt, wait_exponential
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
def fetch_tasks_retry():
response = requests.get(
f"{os.getenv('OA_URL')}/api/v1/tasks",
headers={'Authorization': f"Bearer {os.getenv('API_KEY')}"},
timeout=10
)
response.raise_for_status()
return response.json()['data']
4.2 日志记录
使用logging模块记录运行情况:
python复制import logging
from logging.handlers import RotatingFileHandler
logger = logging.getLogger('oa_automation')
logger.setLevel(logging.INFO)
handler = RotatingFileHandler('oa_auto.log', maxBytes=5*1024*1024, backupCount=3)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
# 在代码中记录
try:
tasks = fetch_tasks_retry()
logger.info(f"成功获取{len(tasks)}条任务")
except Exception as e:
logger.error(f"获取任务失败: {str(e)}")
4.3 性能优化
当任务量很大时,可以考虑:
- 使用缓存减少API调用:
python复制from functools import lru_cache
import time
@lru_cache(maxsize=128, ttl=300) # 缓存5分钟
def get_user_info(user_id):
# 获取用户信息的代码
- 使用多线程处理独立任务:
python复制from concurrent.futures import ThreadPoolExecutor
def send_reminder(task):
# 发送提醒的代码
with ThreadPoolExecutor(max_workers=5) as executor:
executor.map(send_reminder, overdue_tasks)
4.4 部署方案
开发完成后,可以考虑以下几种部署方式:
- 本地运行:适合个人使用
bash复制nohup python oa_auto.py > log.txt 2>&1 &
- 服务器部署:使用systemd管理
ini复制# /etc/systemd/system/oa_auto.service
[Unit]
Description=OA Automation Service
[Service]
User=your_user
WorkingDirectory=/path/to/your/project
ExecStart=/path/to/python /path/to/your/project/oa_auto.py
Restart=always
[Install]
WantedBy=multi-user.target
- 云函数:适合无服务器架构
python复制# 云函数入口文件
def main_handler(event, context):
job()
return "执行成功"
5. 实际应用中的经验分享
在实施这个系统的过程中,我积累了一些宝贵经验:
-
权限申请要趁早:很多OA系统对API调用有限制,提前与IT部门沟通好权限问题,说明自动化能带来的效率提升。我遇到过因为突然增加API调用频率被防火墙拦截的情况。
-
数据验证不能少:OA系统的数据格式可能会变动,一定要做好防御性编程:
python复制def safe_get(data, *keys):
for key in keys:
try:
data = data[key]
except (KeyError, TypeError):
return None
return data
- 提醒频率要合理:初期我设置的提醒太频繁,导致同事抱怨。后来改为:
- 普通任务:截止前1天提醒
- 重要任务:截止前3天、1天、当天各提醒一次
- 紧急任务:每半天提醒一次
- 浏览器自动化要谨慎:如果必须用Selenium,记得:
python复制# 总是添加这些选项
options = webdriver.ChromeOptions()
options.add_argument('--headless') # 无头模式
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome(options=options)
- 定期维护脚本:OA系统升级可能导致脚本失效,建议:
- 每月检查一次脚本运行情况
- 保存历史数据用于比对
- 编写测试用例验证核心功能
这个自动化系统已经稳定运行了一年多,平均每天为我节省2-3小时的手动操作时间。最重要的是,它让我从重复性工作中解放出来,可以专注于更有创造性的工作。
