从真实工作场景出发,解决你每天遇到的重复性工作。
每个项目都来自保康本地政府/企业/乡镇的一线需求,即学即用。
通过对乡镇统计员、中小企业行政、县级单位办公室、茶企/香菇合作社等岗位的调研,汇总以下高频痛点:
以下10个实战项目,每个聚焦一个真实办公痛点,提供完整解决步骤和可直接复用的代码模板。
小王是乡镇统计员,每月要收齐15个村的季度报表。每个村提交的Excel格式不一样——有的列名叫"产量"、有的叫"产粮",有的数据在Sheet1、有的在Sheet2。手工复制粘贴要花2个多小时,还经常粘错行。
pip install pandas openpyxlC:\报表汇总\),确保文件都是.xlsx格式合并报表.py,右键"编辑",粘贴下方代码folder_path 改成你自己的文件夹路径合并报表.py(或在命令提示符中执行 python 合并报表.py),等待几秒钟汇总结果.xlsx,所有数据已合并到一个文件中,每个Sheet标注了来源import pandas as pd
import glob
import os
# 设置存放Excel文件的文件夹路径
folder_path = r"C:\报表汇总"
output_file = "汇总结果.xlsx"
# 获取所有.xlsx文件
excel_files = glob.glob(os.path.join(folder_path, "*.xlsx"))
if not excel_files:
print("❌ 未找到Excel文件,请检查路径")
exit()
all_data = []
sheet_names = []
for file in excel_files:
file_name = os.path.basename(file).replace(".xlsx", "")
# 读取Excel文件中的所有Sheet
xl = pd.ExcelFile(file)
for sheet in xl.sheet_names:
df = pd.read_excel(file, sheet_name=sheet)
# 添加来源信息列
df['来源文件'] = file_name
df['来源Sheet'] = sheet
all_data.append(df)
sheet_names.append(f"{file_name}_{sheet}")
print(f"✅ 已读取: {file_name} - {sheet} ({len(df)}行)")
# 合并所有数据
merged_df = pd.concat(all_data, ignore_index=True)
# 写出到Excel,每个来源一个Sheet
with pd.ExcelWriter(output_file, engine='openpyxl') as writer:
# 总表
merged_df.to_excel(writer, sheet_name='汇总总表', index=False)
# 分表
for df, name in zip(all_data, sheet_names):
# Sheet名不能超过31字符
short_name = name[:31]
df.to_excel(writer, sheet_name=short_name, index=False)
print(f"\n🎉 合并完成!共合并 {len(excel_files)} 个文件,{len(all_data)} 个Sheet")
print(f"📁 输出文件: {output_file}")
print(f"📊 总数据行数: {len(merged_df)}")pd.read_excel() 后加 df = df.rename(columns={"产粮": "产量", "金额(元)": "金额"}) 统一列名。李姐在办公室工作,上级部门发来50份PDF格式的项目申报材料,需要在每份PDF里找到"项目名称""申报金额""负责人"三个字段,汇总成一个Excel表格。她只能打开每份PDF,复制粘贴到Excel,一份一份做,50份做了一整天。
pip install pymupdf pdfplumber pandas openpyxlC:\PDF材料\)提取PDF数据.py,粘贴下方代码keywords 字典里的关键词替换成你需要提取的字段名python 提取PDF数据.pyPDF提取结果.xlsx 中每行是一份PDF,每列是一个提取的字段import fitz # PyMuPDF
import pdfplumber
import pandas as pd
import glob
import os
import re
# 配置
pdf_folder = r"C:\PDF材料"
keywords = {
"项目名称": ["项目名称", "项目名", "课题名称"],
"申报金额(万元)": ["申报金额", "申请金额", "经费", "总金额"],
"负责人": ["负责人", "项目负责人", "申请人", "申报人"],
"单位": ["申报单位", "单位名称", "所在单位"]
}
results = []
pdf_files = glob.glob(os.path.join(pdf_folder, "*.pdf"))
if not pdf_files:
print("❌ 未找到PDF文件")
exit()
for file in pdf_files:
file_name = os.path.basename(file)
print(f"正在处理: {file_name}")
row = {"文件名": file_name}
# 方法1: 用PyMuPDF提取全部文本
doc = fitz.open(file)
full_text = ""
for page in doc:
full_text += page.get_text()
doc.close()
# 方法2: 用pdfplumber(表格提取更准)
table_text = ""
try:
with pdfplumber.open(file) as pdf:
for page in pdf.pages:
tables = page.extract_tables()
for table in tables:
for row_data in table:
table_text += " ".join([str(c) for c in row_data if c]) + "\n"
except:
pass
combined_text = full_text + "\n" + table_text
# 提取每个关键词后面的值
for field_name, patterns in keywords.items():
value = "未找到"
for pattern in patterns:
# 匹配"关键词:XXX"或"关键词 XXX"格式
match = re.search(
rf"{re.escape(pattern)}[::]\s*(.+?)[\n\r]",
combined_text
)
if match:
value = match.group(1).strip()
break
row[field_name] = value
results.append(row)
# 输出Excel
df = pd.DataFrame(results)
df.to_excel("PDF提取结果.xlsx", index=False, engine='openpyxl')
print(f"\n🎉 完成!共处理 {len(results)} 份PDF")
print(f"📁 输出: PDF提取结果.xlsx")年底了,老张要给100个先进个人发通知文件。每份通知除了姓名、单位、奖项不同,其他一模一样。他先做好一个模板,然后复制粘贴100次改名字,手酸眼花搞了一下午,还漏发了3个人。
pip install python-docx pandas openpyxl模板.docx,把需要替换的地方用{{姓名}}{{单位}}{{奖项}}这样的占位符标出来名单.xlsx,第一行表头是"姓名""单位""奖项",下面每一行是一条记录批量生成通知.py,粘贴下方代码template_path 和 data_path 改成你的文件路径python 批量生成通知.py输出通知 文件夹中会生成100份带名字的Word文件from docx import Document
import pandas as pd
import os
# 配置
template_path = r"模板.docx" # Word模板文件
data_path = r"名单.xlsx" # Excel数据文件
output_dir = "输出通知" # 输出文件夹
# 创建输出文件夹
os.makedirs(output_dir, exist_ok=True)
# 读取数据
df = pd.read_excel(data_path)
print(f"📋 共加载 {len(df)} 条记录")
for idx, row in df.iterrows():
# 打开模板
doc = Document(template_path)
# 替换段落中的占位符
for paragraph in doc.paragraphs:
for key, value in row.items():
placeholder = "{{" + str(key) + "}}"
if placeholder in paragraph.text:
# 保留原格式替换
for run in paragraph.runs:
if placeholder in run.text:
run.text = run.text.replace(placeholder, str(value))
# 替换表格中的占位符(如果有表格)
for table in doc.tables:
for table_row in table.rows:
for cell in table_row.cells:
for key, value in row.items():
placeholder = "{{" + str(key) + "}}"
if placeholder in cell.text:
cell.text = cell.text.replace(placeholder, str(value))
# 保存文件
name = str(row.get("姓名", f"第{idx+1}份"))
output_path = os.path.join(output_dir, f"通知_{name}.docx")
doc.save(output_path)
print(f"✅ 已生成: 通知_{name}.docx")
print(f"\n🎉 全部完成!共生成 {len(df)} 份通知文件")
print(f"📁 文件位置: {os.path.abspath(output_dir)}"){{字段名}} 格式即可。注意占位符前后不要有多余空格。小陈在县政府办公室,月底要给全县15个乡镇、30多家企业发会议通知。每封邮件内容基本相同,但附件要根据收件人不同而替换。她一封一封发,每封都要:打开邮箱→点击"写邮件"→粘贴内容→添加附件→输入地址→发送。60封邮件发了一上午。
pip install pandas openpyxl(smtplib和email是Python自带模块,无需安装)收件人名单.xlsx,列名包括"邮箱""姓名""单位""附件路径"(附件路径指对应每个人的附件文件位置)批量发邮件.py,粘贴下方代码python 批量发邮件.pyimport smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import pandas as pd
import os
# ===== 邮箱配置 =====
SMTP_SERVER = "smtp.qq.com" # QQ邮箱;163邮箱用 smtp.163.com
SMTP_PORT = 587 # TLS端口
SENDER_EMAIL = "你的QQ号@qq.com" # 发件邮箱
SENDER_PASS = "你的授权码" # 不是登录密码,是SMTP授权码!
# ===== 读取收件人名单 =====
df = pd.read_excel("收件人名单.xlsx")
print(f"📋 共 {len(df)} 封待发送邮件")
# 邮件内容(HTML格式,支持富文本)
subject_template = "关于召开{月份}月度工作会议的通知"
body_template = """
尊敬的{姓名}:
您好!
根据工作安排,定于{日期}召开{月份}月度工作会议,现将有关事项通知如下:
- 会议时间:{日期} 上午9:00
- 会议地点:保康县人民政府三楼会议室
- 参会人员:{单位}负责同志
- 会议要求:请提前10分钟入场,携带相关材料。
特此通知。
保康县人民政府办公室
{日期}
"""
# 连接SMTP服务器
server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
server.starttls()
server.login(SENDER_EMAIL, SENDER_PASS)
print("✅ 已登录邮箱服务器")
success = 0
fail = 0
for idx, row in df.iterrows():
try:
# 创建邮件对象
msg = MIMEMultipart()
msg["From"] = SENDER_EMAIL
msg["To"] = row["邮箱"]
msg["Subject"] = subject_template.format(
月份=row.get("月份", "本月"),
姓名=row["姓名"]
)
# 正文
body = body_template.format(
姓名=row["姓名"],
单位=row["单位"],
日期=row.get("日期", "2025年1月15日"),
月份=row.get("月份", "本月")
)
msg.attach(MIMEText(body, "html", "utf-8"))
# 添加附件(如果有)
if "附件路径" in row and pd.notna(row["附件路径"]):
attach_path = row["附件路径"]
if os.path.exists(attach_path):
with open(attach_path, "rb") as f:
part = MIMEBase("application", "octet-stream")
part.set_payload(f.read())
encoders.encode_base64(part)
part.add_header(
"Content-Disposition",
f"attachment; filename={os.path.basename(attach_path)}"
)
msg.attach(part)
# 发送
server.sendmail(SENDER_EMAIL, [row["邮箱"]], msg.as_string())
success += 1
print(f"✅ [{success}] 已发送至: {row['邮箱']} ({row['姓名']})")
except Exception as e:
fail += 1
print(f"❌ 发送失败 {row['邮箱']}: {str(e)}")
server.quit()
print(f"\n🎉 发送完毕!成功: {success} 封,失败: {fail} 封")统计局的刘姐每月要处理来自多个渠道的统计数据:有的姓名带空格、有的手机号格式不对、有的重复提交了好几次、有的金额带"元"字。她用Excel的筛选功能一条条改,2000条数据要搞两天。
pip install pandas openpyxl数据清洗.py,粘贴下方代码input_file 和清洗规则中的列名改成你自己的python 数据清洗.py清洗结果.xlsx(干净数据)、重复数据.xlsx(被删掉的重复项)import pandas as pd
import re
# 配置
input_file = "原始数据.xlsx" # 原始数据文件
output_file = "清洗结果.xlsx" # 清洗后输出
# 读取数据
df = pd.read_excel(input_file, dtype=str)
print(f"📋 原始数据: {len(df)} 行, {len(df.columns)} 列")
print(f"📋 列名: {list(df.columns)}")
# ====== 清洗步骤 ======
# 1. 去除所有单元格前后空格
df = df.map(lambda x: x.strip() if isinstance(x, str) else x)
print("✅ 已去除所有单元格前后空格")
# 2. 统一手机号格式(去除横线、空格,补齐11位)
if "手机号" in df.columns:
def clean_phone(p):
if pd.isna(p):
return p
p = re.sub(r'[\s\-\(\)]', '', str(p))
if len(p) == 11 and p.startswith('1'):
return p
return p
df["手机号"] = df["手机号"].apply(clean_phone)
print("✅ 手机号格式已统一")
# 3. 提取金额数字(去掉"元""¥"等)
if "金额" in df.columns:
def extract_amount(val):
if pd.isna(val):
return val
nums = re.findall(r'[\d.]+', str(val))
return nums[0] if nums else val
df["金额"] = df["金额"].apply(extract_amount)
print("✅ 金额字段已清洗(去除了单位文字)")
# 4. 姓名去空格、统一大小写
if "姓名" in df.columns:
df["姓名"] = df["姓名"].str.replace(r'\s+', '', regex=True)
print("✅ 姓名已去空格")
# 5. 去除重复行(基于指定列判断)
if "身份证号" in df.columns:
dup_before = len(df)
df_dups = df[df.duplicated(subset=["身份证号"], keep=False)]
df = df.drop_duplicates(subset=["身份证号"], keep="first")
dedup_count = dup_before - len(df)
print(f"✅ 基于身份证号去重: 删除了 {dedup_count} 条重复数据")
elif "手机号" in df.columns:
dup_before = len(df)
df_dups = df[df.duplicated(subset=["手机号"], keep=False)]
df = df.drop_duplicates(subset=["手机号"], keep="first")
dedup_count = dup_before - len(df)
print(f"✅ 基于手机号去重: 删除了 {dedup_count} 条重复数据")
else:
dedup_count = 0
# 6. 处理缺失值
null_counts = df.isnull().sum()
null_cols = null_counts[null_counts > 0]
if len(null_cols) > 0:
print(f"⚠️ 以下列存在缺失值:")
for col, cnt in null_cols.items():
print(f" - {col}: {cnt} 个空值")
# 输出清洗后数据
df.to_excel(output_file, index=False, engine='openpyxl')
print(f"\n🎉 清洗完成!")
print(f"📁 干净数据: {output_file} ({len(df)} 行)")
# 如果有重复数据,单独输出
if dedup_count > 0:
df_dups.to_excel("重复数据.xlsx", index=False, engine='openpyxl')
print(f"📁 重复数据: 重复数据.xlsx ({len(df_dups)} 行)")办公室的电脑桌面上堆满了文件——通知、报表、照片、会议材料混在一起。每次要找某个文件都要翻很久。小赵每次整理一次要花半小时把文件一个个拖到对应文件夹,过一周又乱了。
文件整理.py,粘贴下方代码target_dir 改为你的桌面路径或其他需要整理的文件夹python 文件整理.pyimport os
import shutil
from pathlib import Path
from datetime import datetime
# ===== 配置 =====
target_dir = Path.home() / "Desktop" # 要整理的文件夹(桌面)
# target_dir = Path(r"C:\下载") # 或改成其他路径
# 文件分类规则(扩展名 → 文件夹名)
categories = {
"文档": [".doc", ".docx", ".txt", ".md", ".wps"],
"表格": [".xls", ".xlsx", ".csv"],
"PDF": [".pdf"],
"图片": [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff", ".webp"],
"压缩包": [".zip", ".rar", ".7z", ".tar", ".gz"],
"演示": [".ppt", ".pptx"],
"视频": [".mp4", ".avi", ".mov", ".wmv", ".flv"],
"代码": [".py", ".js", ".html", ".css", ".json", ".xml", ".sql"],
"其他": []
}
# 收集所有没有被分类的文件扩展名
all_exts = set()
for file in target_dir.iterdir():
if file.is_file():
all_exts.add(file.suffix.lower())
known_exts = set()
for ext_list in categories.values():
known_exts.update(ext_list)
unknown_exts = all_exts - known_exts
if unknown_exts:
categories["其他"].extend(list(unknown_exts))
# 创建分类文件夹
for folder_name in categories:
(target_dir / folder_name).mkdir(exist_ok=True)
# 移动文件
moved_count = 0
for file in target_dir.iterdir():
if file.is_file() and not file.name.startswith("文件整理"):
moved = False
for folder_name, exts in categories.items():
if file.suffix.lower() in exts:
shutil.move(str(file), str(target_dir / folder_name / file.name))
moved_count += 1
moved = True
break
if not moved:
shutil.move(str(file), str(target_dir / "其他" / file.name))
moved_count += 1
# ===== 按日期整理(可选) =====
# 取消下方注释启用:按文件修改日期存入 年/月 子文件夹
"""
for folder_name in categories:
folder_path = target_dir / folder_name
for file in folder_path.iterdir():
if file.is_file():
mtime = os.path.getmtime(file)
date = datetime.fromtimestamp(mtime)
date_dir = folder_path / str(date.year) / f"{date.month:02d}月"
date_dir.mkdir(parents=True, exist_ok=True)
shutil.move(str(file), str(date_dir / file.name))
"""
print(f"🎉 整理完成!共移动了 {moved_count} 个文件")
print(f"📁 请查看 {target_dir}")
# 统计每个分类的文件数
for folder_name in categories:
folder_path = target_dir / folder_name
if folder_path.exists():
count = len(list(folder_path.iterdir()))
print(f" 📂 {folder_name}: {count} 个文件")小周在茶叶合作社工作,要把200张产品照片上传到电商平台。每张照片5-10MB,平台限制单张不超过1MB,而且要统一命名格式为"保康绿茶_001.jpg"。她一张张用画图软件压缩、改名,2个小时还没做完。
pip install PillowC:\原始图片\)图片批量处理.py,粘贴下方代码input_folder、output_folder、name_prefix(文件名前缀)python 图片批量处理.py已处理图片 文件夹中,大小控制在1MB以内from PIL import Image
import os
from pathlib import Path
# ===== 配置 =====
input_folder = r"C:\原始图片" # 原始图片所在文件夹
output_folder = "已处理图片" # 输出文件夹
name_prefix = "保康绿茶_" # 文件名前缀
max_size_mb = 1 # 最大大小(MB)
max_width = 1920 # 最大宽度(px)
quality = 85 # JPEG压缩质量(1-100)
# 支持的图片格式
supported = (".jpg", ".jpeg", ".png", ".bmp", ".tiff", ".webp")
# 创建输出文件夹
os.makedirs(output_folder, exist_ok=True)
# 获取所有图片文件
image_files = [f for f in Path(input_folder).iterdir()
if f.suffix.lower() in supported]
if not image_files:
print("❌ 未找到图片文件")
exit()
print(f"📋 找到 {len(image_files)} 张图片")
total_before = sum(os.path.getsize(f) for f in image_files)
print(f"📊 处理前总大小: {total_before / 1024 / 1024:.1f} MB")
processed = 0
max_bytes = max_size_mb * 1024 * 1024
for idx, img_path in enumerate(image_files, 1):
try:
img = Image.open(img_path)
# 转换RGBA为RGB(处理PNG透明背景)
if img.mode in ("RGBA", "P"):
img = img.convert("RGB")
# 限制最大宽度(等比例缩放)
if img.width > max_width:
ratio = max_width / img.width
new_h = int(img.height * ratio)
img = img.resize((max_width, new_h), Image.LANCZOS)
# 生成输出文件名
ext = ".jpg" # 统一输出为JPEG
output_name = f"{name_prefix}{idx:03d}{ext}"
output_path = os.path.join(output_folder, output_name)
# 保存并控制大小
img.save(output_path, "JPEG", quality=quality, optimize=True)
# 如果文件仍然大于限制,逐步降低质量
file_size = os.path.getsize(output_path)
q = quality
while file_size > max_bytes and q > 10:
q -= 5
img.save(output_path, "JPEG", quality=q, optimize=True)
file_size = os.path.getsize(output_path)
processed += 1
before_size = os.path.getsize(img_path)
after_size = os.path.getsize(output_path)
ratio_pct = (1 - after_size / before_size) * 100
print(f"✅ [{processed}] {img_path.name} → {output_name} "
f"({before_size/1024:.0f}KB→{after_size/1024:.0f}KB, 压缩{ratio_pct:.0f}%)")
except Exception as e:
print(f"❌ 处理失败 {img_path.name}: {str(e)}")
total_after = sum(os.path.getsize(os.path.join(output_folder, f))
for f in os.listdir(output_folder))
print(f"\n🎉 处理完成!共处理 {processed}/{len(image_files)} 张图片")
print(f"📊 处理前: {total_before/1024/1024:.1f} MB → 处理后: {total_after/1024/1024:.1f} MB")
print(f"📁 文件位置: {os.path.abspath(output_folder)}")小吴每天上班第一件事是打开县政府网站,看有没有新的补贴公示、招标公告、政策文件。如果今天没更新就白看了,如果有更新就得手动复制粘贴到Excel里做台账。一个月下来,每天花15分钟,还容易漏掉重要通知。
pip install requests beautifulsoup4 pandas lxml网页监控.py,粘贴下方代码target_url 改为你要监控的网站地址item_selector(文章列表的CSS选择器)python 网页监控.pyimport requests
from bs4 import BeautifulSoup
import pandas as pd
from datetime import datetime
import os
# ===== 配置 =====
target_url = "http://example.gov.cn/notice" # 替换为目标网站URL
output_file = "网页监控台账.xlsx"
# CSS选择器规则(根据目标网站的HTML结构调整)
# 示例:如果公告列表是 - 标题日期
item_selector = "ul.news-list li" # 列表项选择器
title_selector = "a" # 标题所在标签
link_selector = "a" # 链接所在标签
date_selector = "span" # 日期所在标签
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/120.0.0.0 Safari/537.36"
}
print(f"🌐 正在访问: {target_url}")
try:
resp = requests.get(target_url, headers=headers, timeout=15)
resp.encoding = resp.apparent_encoding
soup = BeautifulSoup(resp.text, "lxml")
except Exception as e:
print(f"❌ 访问失败: {str(e)}")
exit()
# 提取文章列表
items = soup.select(item_selector)
print(f"📋 找到 {len(items)} 条记录")
data = []
for item in items:
title_el = item.select_one(title_selector) if title_selector else item
title = title_el.get_text(strip=True) if title_el else "无标题"
link_el = item.select_one(link_selector) if link_selector else item
link = ""
if link_el and link_el.name == "a" and link_el.get("href"):
href = link_el["href"]
if href.startswith("/"):
from urllib.parse import urljoin
link = urljoin(target_url, href)
elif href.startswith("http"):
link = href
else:
link = href
date_el = item.select_one(date_selector) if date_selector else None
date_text = date_el.get_text(strip=True) if date_el else ""
data.append({
"标题": title,
"链接": link,
"日期": date_text,
"抓取时间": datetime.now().strftime("%Y-%m-%d %H:%M")
})
# 读取已有的台账,合并去重
if os.path.exists(output_file):
existing = pd.read_excel(output_file)
new_df = pd.DataFrame(data)
combined = pd.concat([existing, new_df], ignore_index=True)
combined = combined.drop_duplicates(subset=["标题", "链接"], keep="last")
else:
combined = pd.DataFrame(data)
combined.to_excel(output_file, index=False, engine='openpyxl')
# 输出新增内容
new_count = len(combined) - (len(pd.read_excel(output_file)) if os.path.exists(output_file) else 0)
print(f"\n🎉 抓取完成!")
print(f"📁 台账文件: {output_file} (共 {len(combined)} 条)")
print(f"🆕 新增内容: {len(data)} 条(本批次)")
# 显示最新5条
print("\n📰 最新内容预览:")
for i, row in enumerate(data[:5]):
print(f" {i+1}. {row['标题'][:40]}...")
python,参数填脚本的完整路径人事科的小杨每个月导出考勤机里的打卡记录,几百条数据:张三 2025-01-15 08:12:23,张三 2025-01-15 17:45:38……她要在Excel里算每个人每天上班几小时、有没有迟到早退、加班多少分钟。40个人的数据,每次对几个小时眼睛都花了。
pip install pandas openpyxl考勤统计.py,粘贴下方代码python 考勤统计.py考勤统计结果.xlsx,包含每个人每天的出勤情况汇总import pandas as pd
from datetime import datetime, timedelta
# ===== 配置 =====
input_file = "考勤原始数据.xlsx" # 从考勤机导出的原始数据
output_file = "考勤统计结果.xlsx"
# 上下班时间设置
MORNING_START = "08:00" # 上午上班时间
MORNING_END = "12:00" # 上午下班时间
AFTERNOON_START = "13:00" # 下午上班时间
AFTERNOON_END = "17:30" # 下午下班时间
# 迟到/早退标准(分钟)
LATE_THRESHOLD = 15 # 超过X分钟算迟到
EARLY_THRESHOLD = 15 # 提前X分钟走算早退
# 读取原始数据
df = pd.read_excel(input_file)
print(f"📋 原始记录: {len(df)} 条")
print(f"📋 列名: {list(df.columns)}")
# 标准化列名(通常考勤机导出的列名可能是"姓名/日期/时间"或"员工/打卡时间")
df.columns = [str(c).strip() for c in df.columns]
# 假设列名包含"姓名""日期""时间"关键词,自动匹配
name_col = [c for c in df.columns if "姓名" in c or "员工" in c or "名称" in c]
date_col = [c for c in df.columns if "日期" in c or "日" in c]
time_col = [c for c in df.columns if "时间" in c or "打卡" in c or "考勤" in c]
if not name_col or not date_col or not time_col:
print("❌ 无法自动识别列名,请检查数据格式")
print(f" 找到的列: {list(df.columns)}")
print(" 请确保列名包含:姓名、日期、时间")
exit()
name_col, date_col, time_col = name_col[0], date_col[0], time_col[0]
# 转换日期和时间列为标准格式
df[date_col] = pd.to_datetime(df[date_col]).dt.date
df[time_col] = pd.to_datetime(df[time_col], format='%H:%M:%S', errors='coerce')
df[time_col] = df[time_col].dt.time
# 按人和日期分组,每人每天取第一次打卡(上班)和最后一次打卡(下班)
records = []
for (name, date), group in df.groupby([name_col, date_col]):
times = sorted(group[time_col].dropna())
if len(times) < 2:
# 只有一次打卡记录,无法计算
records.append({
"姓名": name,
"日期": date,
"上班打卡": str(times[0]) if times else "无",
"下班打卡": "无",
"出勤时长(小时)": 0,
"状态": "打卡异常"
})
continue
first_punch = times[0]
last_punch = times[-1]
# 计算总在岗时间
def time_diff_minutes(t1, t2):
dt1 = datetime.combine(datetime.today(), t1)
dt2 = datetime.combine(datetime.today(), t2)
return (dt2 - dt1).total_seconds() / 60
total_minutes = time_diff_minutes(first_punch, last_punch)
# 判断迟到
morning_start = datetime.strptime(MORNING_START, "%H:%M").time()
late_minutes = time_diff_minutes(morning_start, first_punch)
if late_minutes > LATE_THRESHOLD:
late_status = f"迟到{int(late_minutes)}分钟"
else:
late_status = "正常"
# 判断早退
afternoon_end = datetime.strptime(AFTERNOON_END, "%H:%M").time()
early_minutes = time_diff_minutes(last_punch, afternoon_end)
if early_minutes > EARLY_THRESHOLD:
early_status = f"早退{int(early_minutes)}分钟"
else:
early_status = "正常"
records.append({
"姓名": name,
"日期": str(date),
"上班打卡": str(first_punch),
"下班打卡": str(last_punch),
"出勤时长(小时)": round(total_minutes / 60, 1),
"出勤状态": late_status,
"离开状态": early_status
})
result = pd.DataFrame(records)
# 每个人汇总统计
summary = result.groupby("姓名").agg(
出勤天数=("日期", "count"),
总时长_小时=("出勤时长(小时)", "sum"),
平均时长_小时=("出勤时长(小时)", "mean"),
迟到次数=("出勤状态", lambda x: sum("迟到" in str(s) for s in x)),
早退次数=("离开状态", lambda x: sum("早退" in str(s) for s in x))
).reset_index()
summary["总时长_小时"] = summary["总时长_小时"].round(1)
summary["平均时长_小时"] = summary["平均时长_小时"].round(1)
# 输出到Excel(两个Sheet)
with pd.ExcelWriter(output_file, engine='openpyxl') as writer:
result.to_excel(writer, sheet_name="每日明细", index=False)
summary.to_excel(writer, sheet_name="汇总统计", index=False)
print(f"\n🎉 考勤统计完成!")
print(f"📁 输出文件: {output_file}")
print(f"📊 每日明细: {len(result)} 条记录")
print(f"📊 汇总统计: {len(summary)} 人")
# 显示汇总
print("\n📋 考勤汇总:")
for _, row in summary.iterrows():
print(f" {row['姓名']}: 出勤{row['出勤天数']}天, "
f"共{row['总时长_小时']}小时, "
f"迟到{row['迟到次数']}次, "
f"早退{row['早退次数']}次")档案室的老周要整理历史档案:500多页上世纪90年代的纸质统计表、手写报表、旧式合同。这些资料只有纸质版或扫描件,领导要电子版方便查询。如果手工打字录入,500页一年都做不完。他听说有OCR技术,但不知道怎么用。
C:\Program Files\Tesseract-OCR\tesseract.exe)pip install pytesseract pillow pandas openpyxlOCR识别.py,粘贴下方代码pytesseract.pytesseract.tesseract_cmd 改成你的安装路径python OCR识别.pyOCR识别结果.xlsx,每张图片识别的文字分段保存import pytesseract
from PIL import Image
import pandas as pd
import os
from pathlib import Path
# ===== 配置 =====
# Tesseract安装路径(根据实际安装位置修改)
pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"
input_folder = r"C:\扫描件图片" # 扫描件图片文件夹
output_file = "OCR识别结果.xlsx"
# 支持的语言:chi_sim=简体中文, eng=英文, chi_sim+eng=中英混合
OCR_LANG = "chi_sim+eng"
supported = (".jpg", ".jpeg", ".png", ".tiff", ".tif", ".bmp")
# 获取图片文件
image_files = [f for f in Path(input_folder).iterdir()
if f.suffix.lower() in supported]
if not image_files:
print("❌ 未找到图片文件")
exit()
print(f"📋 找到 {len(image_files)} 张图片")
results = []
for idx, img_path in enumerate(image_files, 1):
try:
print(f"⏳ [{idx}/{len(image_files)}] 正在识别: {img_path.name}")
# 打开图片
img = Image.open(img_path)
# 图片预处理:转为灰度图,提高识别率
img = img.convert("L")
# 调整对比度(可选)
# from PIL import ImageEnhance
# enhancer = ImageEnhance.Contrast(img)
# img = enhancer.enhance(2.0)
# 执行OCR识别
text = pytesseract.image_to_string(img, lang=OCR_LANG)
# 清洗结果
lines = [line.strip() for line in text.split("\n") if line.strip()]
results.append({
"文件名": img_path.name,
"识别文字": "\n".join(lines),
"行数": len(lines),
"状态": "成功"
})
print(f"✅ 识别完成: {len(lines)} 行文字")
except Exception as e:
results.append({
"文件名": img_path.name,
"识别文字": "",
"行数": 0,
"状态": f"失败: {str(e)}"
})
print(f"❌ 识别失败 {img_path.name}: {str(e)}")
# 输出Excel
df = pd.DataFrame(results)
df.to_excel(output_file, index=False, engine='openpyxl')
success_count = sum(1 for r in results if r["状态"] == "成功")
print(f"\n🎉 OCR识别完成!")
print(f"📁 输出: {output_file}")
print(f"📊 成功: {success_count}/{len(results)} 张")
# 显示前3张的识别内容预览
print("\n📝 识别预览:")
for r in results[:3]:
if r["状态"] == "成功":
preview = r["识别文字"][:100].replace("\n", " | ")
print(f" 📄 {r['文件名']}: {preview}...")| 🔍 痛点 | 📘 对应课程 | 📖 阶段 | ⭐ 难度 |
|---|---|---|---|
| 批量改文件名/整理文件 | 第一个Python脚本 + 文件夹整理工具 | 阶段1 工具 | 容易 |
| 合并多个Excel报表 | 自动化Excel报表生成器 + 多表数据合并工具 | 阶段2 工具 | 容易 |
| 数据去重/清洗/格式化 | 数据去重清洗工具 + 数据格式统一工具 | 工具 阶段2 | 容易 |
| 批量压缩/裁剪图片 | AI辅助图片批量处理 + 图片批量处理工具 | 阶段1 工具 | 容易 |
| PDF文本提取 | PDF数据提取工具 | 工具 | 容易 |
| 文字识别OCR | OCR文字识别工具 + 纸质档案数字化 | 工具 阶段3 | 容易 |
| Word模板批量生成 | Word模板批量生成工具 + 模块A2 Word/PDF自动化 | 工具 阶段3 | 容易 |
| 薪酬个税计算 | 薪税计算器工具 | 工具 | 容易 |
| VLOOKUP模糊匹配 | 智能VLOOKUP合并工具 | 工具 | 中等 |
| 工资条/通知单拆分 | 模块A1 Excel自动化 | 阶段3 | 中等 |
| PDF表格提取 | 模块A2 Word/PDF自动化 | 阶段3 | 中等 |
| 自动发邮件/通知 | 模块A3 邮件/通知自动化 | 阶段3 | 中等 |
| 网页数据采集 | 模块A4 数据采集与清洗 + 网页数据抓取工具 | 阶段3 工具 | 中等 |
| 农产品价格分析 | 农产品价格趋势图 + 数据可视化 | 阶段2 | 中等 |
| 财务数据透视分析 | 财务数据透视分析表 | 阶段2 | 较难 |
| 搭建自动化报表系统 | 模块A5 定时任务与报表系统 + 智能报表系统 | 阶段3 | 较难 |
| AI客服/知识库问答 | 保康文旅问答Bot + 方向B AI客服Bot | 阶段2 阶段3 | 较难 |
| 公文格式自动排版 | 公文格式排版助手工具 + 编辑助手 | 工具 | 较难 |
| 进销存/库存管理 | 方向C 低代码企业管理系统 | 阶段3 | 较难 |
| 企业综合数据看板 | 方向B 数据看板 + Flask | 阶段3 | 困难 |
| 全流程办公自动化 | 模块A6 综合项目·办公提效工具箱 | 阶段3 | 困难 |