档案软件二次开发太贵?教你用Python脚本低成本对接
一、技术方案选型与环境搭建
面对老旧或封闭的档案管理系统,厂商往往报价高昂进行二次开发。实际上,我们可以利用Python的RPA(机器人流程自动化)技术,模拟人工操作在浏览器界面录入数据,从而绕过系统底层限制,实现零成本对接。本方案采用Python 3.9 + Selenium库,无需破解数据库,只需在图形界面操作即可。
需要在你的控制端电脑或服务器上安装运行环境。请直接去Python官网下载 Python 3.9.7 版本安装包,安装时务必勾选 "Add Python to PATH" 选项。
安装完成后,打开命令行工具(Win键+R输入cmd),依次执行以下命令安装核心依赖库:
pip install selenium==4.1.0 webdriver-manager flask requests
这里我们使用了 Selenium 控制浏览器,webdriver-manager 自动管理浏览器驱动,Flask 用于将脚本封装成API接口供其他系统调用。请确保你的系统已安装 Google Chrome 浏览器,这是Selenium运行的基础。
二、目标系统元素定位分析
在编写代码前,必须获取档案管理系统中关键操作点的“坐标”。打开Chrome浏览器,按 F12 键调出开发者工具。点击左上角的箭头图标(选择元素),将鼠标移动到档案系统的 用户名输入框、密码输入框、登录按钮、档案上传按钮 以及 保存按钮 上。
在Elements面板中,右键点击高亮的HTML标签,选择 Copy -> Copy XPath。将这些XPath路径记录下来,后续代码中会直接使用。例如,用户名框的XPath可能是 //[@id="username"],登录按钮是 //[@id="loginBtn"]。请务必确保你复制的路径是唯一的,否则会导致脚本定位失败。
三、编写核心自动化操作脚本
新建一个名为 archive_bot.py 的文件。我们将编写一个类,专门处理登录、上传文件和提交数据的逻辑。以下代码实现了自动登录档案系统并模拟上传文件的全过程,请根据你刚才复制的XPath替换代码中的 target_xpath 部分。
```python
import time
import os
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.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
class ArchiveBot:
def __init__(self):
配置Chrome无头模式,后台运行不弹出浏览器窗口
options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--disable-gpu')
options.add_argument('--no-sandbox')
自动下载并匹配ChromeDriver版本
service = Service(ChromeDriverManager().install())
self.driver = webdriver.Chrome(service=service, options=options)
self.wait = WebDriverWait(self.driver, 20) 设置显式等待20秒
def login(self, url, username, password):
"""
登录档案系统
"""
try:
self.driver.get(url)
print(f"正在访问: {url}")
定位用户名输入框并输入
user_input = self.wait.until(EC.presence_of_element_located((By.XPATH, '//[@id="username"]')))
user_input.send_keys(username)
定位密码输入框并输入
pass_input = self.wait.until(EC.presence_of_element_located((By.XPATH, '//[@id="password"]')))
pass_input.send_keys(password)
点击登录按钮
login_btn = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//[@id="loginBtn"]')))
login_btn.click()
等待登录成功后的特征元素出现,例如"欢迎页"的某个标题
self.wait.until(EC.presence_of_element_located((By.XPATH, '//[@id="dashboard"]')))
print("登录成功")
return True
except Exception as e:
print(f"登录失败: {str(e)}")
return False
def upload_archive(self, file_path, title):
"""
上传档案文件并填写元数据
"""
try:
1. 点击新建或上传按钮
upload_btn = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//[@id="btn-upload"]')))
upload_btn.click()
time.sleep(2) 等待弹窗加载
2. 处理文件上传控件
注意:很多系统的文件上传是input type=file,直接send_keys即可
如果是复杂的Flash上传,可能需要使用pyautogui模拟键盘路径
file_input = self.driver.find_element(By.XPATH, '//input[@type="file"]')
file_input.send_keys(os.path.abspath(file_path))
print(f"文件路径已填入: {file_path}")

3. 填写档案标题元数据
title_input = self.wait.until(EC.presence_of_element_located((By.XPATH, '//[@id="archive-title"]')))
title_input.clear()
title_input.send_keys(title)
4. 点击保存按钮
save_btn = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//[@id="btn-save"]')))
save_btn.click()
5. 等待保存成功的提示框
self.wait.until(EC.presence_of_element_located((By.XPATH, '//div[contains(text(), "保存成功")]')))
print("档案上传并保存成功")
return True
except Exception as e:
print(f"上传过程出错: {str(e)}")
截图保存用于调试
self.driver.save_screenshot("error.png")
return False
def close(self):
self.driver.quit()
```
上述代码中,send_keys 是核心,它模拟了键盘输入。对于文件上传,Selenium可以直接将本地文件的绝对路径发送给 input 标签,这比模拟鼠标点击“选择文件”弹窗更稳定。如果你的系统没有标准的 input 标签,你需要安装 pyautogui 库,并使用 pyautogui.write() 和 pyautogui.press('enter') 来模拟系统级弹窗操作。
四、封装为Web接口服务
为了让其他业务系统能够调用这个脚本,我们使用Flask将其封装为一个HTTP接口。这样,当你的OA系统有新档案归档时,只需调用这个HTTP接口,参数传递文件路径和标题,即可自动触发档案系统的录入。在同目录下新建 app.py:
```python
from flask import Flask, request, jsonify
from archive_bot import ArchiveBot
import threading
app = Flask(__name__)
初始化机器人实例(注意:多线程环境下需谨慎处理driver实例,这里简化处理)
bot = ArchiveBot()
LOGIN_URL = "http://192.168.1.100:8080/login" 替换为你的档案系统地址
USER = "admin"
PASS = "123456"
@app.route('/api/upload', methods=['POST'])
def upload_api():
获取前端传来的JSON参数
data = request.json
file_path = data.get('file_path')
title = data.get('title')
if not file_path or not title:
return jsonify({"status": "error", "msg": "缺少参数"}), 400
定义一个线程任务来执行,避免阻塞Flask主线程
def task():
try:
每次任务重新登录以确保会话有效
if bot.login(LOGIN_URL, USER, PASS):
bot.upload_archive(file_path, title)
bot.close()
except Exception as e:
print(f"后台任务异常: {e}")
threading.Thread(target=task).start()
return jsonify({"status": "success", "msg": "任务已提交,正在后台处理..."})
if __name__ == '__main__':
启动Flask服务,监听5000端口
app.run(host='0.0.0.0', port=5000)
```
这段代码创建了一个 /api/upload 的接口。通过 threading 模块,我们将耗时的浏览器操作放在后台线程执行,保证接口能快速返回响应,避免调用方超时。
五、部署与运行验证
所有代码准备就绪后,即可进行本地测试。在命令行中进入项目目录,执行以下命令启动服务:
python app.py
看到输出 Running on http://0.0.0.0:5000 表示服务启动成功。此时,你需要准备一个测试用的PDF文件,例如 C:\test.pdf。使用Postman或者curl命令发送请求进行测试:
```bash
curl -X POST http://127.0.0.1:5000/api/upload -H "Content-Type: application/json" -d "{\"file_path\": \"C:\\\\test.pdf\", \"title\": \"测试档案标题\"}"
```
执行命令后,观察命令行窗口的日志输出。你应该能看到“正在访问”、“登录成功”、“文件路径已填入”、“档案上传并保存成功”的日志流。如果遇到报错,检查项目目录下是否生成了 error.png,查看截图分析是哪个元素未定位到。
如果是在Linux服务器部署,由于Linux通常没有图形界面,你需要安装Xvfb(虚拟显示):
sudo apt-get install xvfb
然后修改启动命令为:
xvfb-run python app.py
这样,Selenium就能在虚拟显示器中运行Chrome,完美解决无头环境下的自动化需求。通过这套方案,你完全不需要支付昂贵的接口授权费或二次开发费,仅需维护一套Python脚本即可实现数据的无缝流转。