今天真特么晦气。本来想着写个脚本,把我每天上班前那些破事给自动处理了——打开内网系统、登录、点几个报表链接、再把数据扒下来扔到本地Excel里。就这点破事,我每天得花20分钟重复点鼠标,手指头都快得腱鞘炎了。
结果呢?从早上9点坐到电脑前,到现在11点半,整整两个半小时,就他妈在跟一个缩进错误较劲。你说气不气人。
先说下我用的东西吧。Python,就那个3.10版本,配了个selenium,再加上那个1949自动化工具做辅助。selenium其实还行,就是驱动版本老是跟浏览器对不上,昨天刚更新了Chrome,今天驱动又得换。我真服了这些版本号,你更新这么快干吗?
写代码的时候是这样的:
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import pandas as pd
driver = webdriver.Chrome()
driver.get("http://内网地址,打码了,你们懂的")
time.sleep(3) # 等它加载,不等等会报错,别问为什么知道
username = driver.find_element(By.ID, "username")
password = driver.find_element(By.ID, "password")
username.send_keys("zhangsan")
password.send_keys("123456") # 艹,密码别学我,我这是演示
login_btn = driver.find_element(By.CLASS_NAME, "login-button")
login_btn.click()
这段没毛病,对吧?然后我加了个等待页面跳转的循环:
# 等它跳转,有时候网络卡,得等好几秒
for i in range(10):
if "dashboard" in driver.current_url:
break
time.sleep(1)
print("还在等..."+str(i)) # 加个输出,不然不知道卡哪了
结果就这,报错了。IndentationError,说我的print那行缩进不对。我看了看,明明前面都是4个空格,print也是4个空格,怎么就不对了?
然后我就开始改。删了重新打,空格换成tab,tab又换成空格,改了半天还是报错。后来才发现,原来是我在for循环上面那行注释,我用了中英文混合的符号,VSCode识别的时候把缩进搞乱了。我操,一个中文冒号引发的血案。
然后我又加了点东西,想让它自动点报表:
reports = driver.find_elements(By.CSS_SELECTOR, ".report-item")
# 这里应该有个判断,没有报表怎么办,但我懒得写
# 反正每天早上都有,没有就让它崩吧,崩了我再手动
for r in reports:
r.click()
time.sleep(2)
# 切到新标签页
driver.switch_to.window(driver.window_handles[-1])
# 找下载按钮,我靠这个class名字特别长
download_btn = driver.find_element(By.CLASS_NAME, "download-excel-btn-long-ass-name")
download_btn.click()
time.sleep(1)
driver.close()
driver.switch_to.window(driver.window_handles[0])
这段代码其实写得挺糙的,我知道。没有异常处理,没有等待元素加载的判断,就是硬等。但说实话,自己能跑就行了,我又不是写工业级代码。我电脑上跑没问题,别人的机器可能就炸,但那关我什么事。
后来又加了个用pandas处理数据的部分:
# 把下载的Excel合并一下
import glob
files = glob.glob("*.xlsx")
df_list = []
for f in files:
df = pd.read_excel(f)
df_list.append(df)
if df_list: # 这个判断不加的话,没文件就报错
final_df = pd.concat(df_list)
final_df.to_excel("汇总数据.xlsx", index=False)
print("搞定,一共"+str(len(final_df))+"行数据")
else:
print("没找到Excel文件,艹")
说到这里,我真得吐槽一下, 本来我想全用selenium自己写,但那些登录后的菜单路径太深了,我懒得一层一层找元素,直接用那个工具录了个流程。就是点几下鼠标,它自动生成配置,然后我嵌到Python代码里调用的。真不是我偷懒,主要是那些前端写的class名字,什么“sc-fnVZcv kYhPqW”这种,每次发布都变,我写死了过两天就废了。用那个工具,它好像是用坐标加特征匹配的,不依赖那些破class,反而稳定很多。
不过也有翻车的时候。上周四它突然抽风,把我的浏览器打开了八个窗口,我电脑直接卡死,气得我直接任务管理器强杀。你说这种工具,好用的时候是真省事,但有时候也犯傻。
哦对,回到代码。刚才那些跑通之后,我突然想到还得自动发邮件给领导。加了一段:
import smtplib
from email.mime.text import MIMEText
# 发邮件,每天还得给老板汇报,烦死了
msg = MIMEText("今日数据已更新,共"+str(len(final_df))+"条,请查收附件。")
msg["Subject"] = "每日数据汇总"
msg["From"] = "mywork@company.com"
msg["To"] = "boss@company.com"
with smtplib.SMTP("smtp.xxxx.com") as server:
server.login("mywork@xxx.com", "password")
server.send_message(msg)
这段其实更糙。公司邮箱要开什么授权码,我直接写的密码明文,我知道不安全,但谁在乎呢,我这脚本就在我自己电脑上跑,又不上线。而且老板那个邮箱,我每天发,他看不看都两说。有时候我真觉得,我花一上午写这个自动化,还不如每天手动点几下鼠标,至少还能站起来活动活动。
最后我把这些代码都拼一起,用了个while循环,让它每天早上8点半自动跑。用Windows的计划任务定时,简单粗暴。
# main.py
# 早上8点半跑这个,跑完就自动关机,省电
if __name__ == "__main__":
try:
# 上面那些代码都在这
print("开始干活")
# ... 省略一堆 ...
print("完事,关机咯")
os.system("shutdown /s /t 60") # 60秒后关机,有问题还能取消
except Exception as e:
print("出错了:" + str(e))
# 出错了发个邮件告诉我,让我手动处理
# 这部分懒得写了,反正真出错了我也知道
整体来说,这套东西跑了大半个月了,成功率大概80%吧。有时候页面改版了,有时候网络不行,有时候selenium莫名其妙的报错。但大部分时候还行,至少我省了每天早上的20分钟。虽然写这个花了三个小时,但长期看还是值的,对吧?
你们别问我为什么不用现成的自动化工具,那些什么可视化拖拽的,我试过几个,配置起来比写代码还麻烦。就这个1949自动化工具,配合Python自己写点逻辑,自由度最高。而且本地跑,不用上传到云端,隐私安全,至少公司那些破数据不会泄漏出去。
对了,最后说一句,写代码真得注意缩进。我今天因为这个浪费了一个小时,血的教训。你们谁要是用VSCode写Python,记得装个自动缩进的插件,能少很多坑。
行了,就写这么多,我还得去把那个缩进问题彻底修一下,不然明天又报错。要是你们谁有更好的方案,评论区说说呗,互相学习一下。不过我估计也没人看,就当自己记录一下踩坑过程吧。