ホームページ >バックエンド開発 >Python チュートリアル >PythonでERPシステムデータを自動入力する方法
ソフトウェア: Pycharm
環境: Python 3.7。 9 (互換性上の理由により、顧客が異なるオペレーティング システムを使用している可能性があることを考慮)
テクニカル ライブラリ: リクエスト、パンダ、Pyqt5 など (詳細については依存関係ファイルを参照)
顧客要求ドキュメントの分析とコミュニケーションを通じて、大まかに次の要件があります:
「単一番号所有権に基づいてデータを 3 つのインターフェイスにバッチで送信する」 "
GUI 操作インターフェイスが必要
さまざまな営業マンのログインをサポート
一般的にPOSTデータ入稿とGUI開発だそうです。
このセクションでは主にクローラー技術を使用します。何千年も変わらない手順は、最初に Web ページを分析することです。
パケット キャプチャにより、パスワードが平文であることがわかり、難易度が半分になります。その後、正しいパスワードを使用してログインします。ログイン成功後の戻り値を分析します。
def login(self, username: str, password: str): """ 登录 """ url = "http://cloud.tiamaes.com:11349/erp/portal.bootstrap/SSOLoginAction/login.do" data = { "_tp_data": '{"parameters":{"userName":' + username + ',"pwd":' + password + '},"rowsets":{},"headers":{},"requestComponent":"0"}' } data = parse.urlencode(data).replace("+", "") resp = requests.post(url, headers=self.headers, data=data, verify=False) self.IDENTIFIER = resp.json()["headers"]["IDENTIFIER"] return self.IDENTIFIER
ログインに成功すると、「IDENTIFIER」パラメータが返されることがわかります。値は暗号化された文字列です。これは明らかです。リテラルを見ただけで、つまり、これが役立つはずであることがわかっているので、最初に書き留めてください。
テスト アカウントを使用しているため、このアカウントによって送信されたデータは削除されます。他のアカウントに無効なデータが多量に注入されないように、実際のアカウントは削除されません。ここにエントリーします。ビジネスコードで説明されています。
車両情報の取得
分析の結果、顧客から車両情報が提供されたものの、まだ多くの情報が不足していることが判明しました。自分に必要な情報を補充する。パケット キャプチャにより、車両番号を入力すると Ajax リクエストが開始され、フォーム内のその他の情報が Ajax リクエストによって返されたデータであることがわかりました。
def get_car_details(self, car_no: str, IDENTIFIER: str): """ 获取车辆信息 """ # print(self.IDENTIFIER) url = "http://cloud.tiamaes.com:11349/money/basis.inter/JwBusAction/getCacheJwBusByNo.do" data = { '_tp_data': '{"parameters": {"busNo": ' + str(car_no) + ', "dsName": "83"}, "rowsets": {}, "headers": {"IDENTIFIER": ' + IDENTIFIER + '}, "requestComponent": "0"}' } data = parse.urlencode(data).replace("+", "") resp = requests.post(url, headers=self.headers, data=data, verify=False) rows = resp.json()["rowsets"]["com.tp.basis.entity.entity.bus.BaJwBus"]["rows"][0] return rows
人事情報の取得
パケット経由のフォームに人事情報が見つかりませんでしたキャプチャし、後でそれを発見しました。 関連するデータがページ上で見つかりました。
これは少し面倒で、データを照合するには正規表現を使用する必要があります。
def get_personal_info(self, IDENTIFIER: str): """ 获取个人信息 """ url = "http://cloud.tiamaes.com:11349/money/money.action/CharteredAction/showDetail.do" data = { '_tp_data': '{"parameters":{"dsName":"83","method":"add","recId":"-1"},"rowsets":{},"headers":{"IDENTIFIER":' + IDENTIFIER + '},"requestComponent":"1"}' } data = parse.urlencode(data).replace("+", "") resp = requests.post(url, headers=self.headers, data=data, verify=False) json_data = eval(re.findall(r'<code>.*?"rows":\[(.*?)\]', resp.text)[0]) return json_data
リクエストを開始してデータを送信します
ログインによって返された識別子、車両情報、従業員情報などを取得します。顧客と通信することです。指定されたデータを組み合わせてリクエストを開始します。なお、リクエストパラメータはURLエンコードに変換する必要がありますが、このクローラで最も面倒な部分でもありますので、ここではリクエストで送信する必要があるパラメータを示します。
#パラメータが多く、形式要件も比較的厳しく、開発プロセス全体の中で、ここのデバッグも最も時間がかかります。デバッグ後はコードを簡略化する必要がありますが、私はデバッグ後にマージする必要があるマージを変更するのが面倒なので、このセクションは比較的冗長です。
def submit_data(self, i: dict, IDENTIFIER: str): """ 众意数据提交 """ personal_info = self.get_personal_info(IDENTIFIER) # 获取个人信息 personal_info_data = str(personal_info).replace("'", '"') # 将personal_info转换为字符串 url = "http://cloud.tiamaes.com:11349/money/money.action/CharteredAction/saveForm.do" print(f'开始处理--{i["单号归属"]}--数据') memo = f'工单号{i["工单号"]}、餐费{i["餐费"]}、住宿{i["住宿"]}、过路过桥费{i["过路过桥费"]}、油费{i["油费"]}、备注{i["备注"]}' # 拼接备注信息 car_infos = self.get_car_details(str(i["车号"]), IDENTIFIER) # 获取车辆信息 pay_type = { "现金": "3", "转账": "2", "欠款": "1" } single_and_double = { "单程": "1", "双程": "2" } colType = pay_type[i["结账方式"]] # 获取结账方式编码 oddEven = single_and_double[i["单双程"]] # 获取单双程编码 now_date = datetime.datetime.now().date().strftime("%Y-%m-%d") # 获取当前日期 .......(此处省略) data["_tp_data"] = data["_tp_data"].replace('"dsName":"83"', '"dsName":"82"') data = parse.urlencode(data).replace("+", "") # 将字典转换成url编码 resp = requests.post(url, headers=self.headers, data=data, verify=False).json() order_id = resp["rowsets"]["com.tp.money.entity.basic.Chartered"]["rows"][0]["recNo"] # 获取订单编号 i["包车单号"] = order_id return data
GUI 開発は比較的単純です。美化したくない場合は、Pyqt のネイティブ プラグインで十分です。以前のプロジェクトの経験をここに借りました。一部の知識のみを使用して、境界のないインターフェースと適切な美化を実現しました。
from PyQt5.QtCore import Qt from PyQt5.QtGui import QColor from PyQt5.QtWidgets import (QFrame, QMessageBox, QGraphicsDropShadowEffect) from Ui import login_ui from Ui.submit_ui_main import MySubmitForm from submit import TransitSubmit class MyLogin(login_ui.Ui_LoginForm, QFrame): def __init__(self, submit: TransitSubmit): super().__init__() # self.IDENTIFIER = None # self.my_main_window = None self.setupUi(self) self.submit = submit # 设置无边框模式 self.setWindowFlag(Qt.FramelessWindowHint) # 将界面设置为无框 self.setAttribute(Qt.WA_TranslucentBackground) # 将界面属性设置为半透明 self.shadow = QGraphicsDropShadowEffect() # 设定一个阴影,半径为10,颜色为#444444,定位为0,0 self.shadow.setBlurRadius(10) self.shadow.setColor(QColor("#444444")) self.shadow.setOffset(0, 0) self.frame.setGraphicsEffect(self.shadow) # 为frame设定阴影效果 # ------------------------------------------------ self.show() self.pushButton_3.clicked.connect(self.close) # 关闭按钮 self.pushButton_login.clicked.connect(self.do_login) # 登录按钮 # 以下是控制窗口移动的代码 def mousePressEvent(self, event): # 鼠标左键按下时获取鼠标坐标,按下右键取消 if event.button() == Qt.LeftButton: self.m_flag = True self.m_Position = event.globalPos() - self.pos() event.accept() elif event.button() == Qt.RightButton: self.m_flag = False def mouseMoveEvent(self, QMouseEvent): # 鼠标在按下左键的情况下移动时,根据坐标移动界面 if Qt.LeftButton and self.m_flag: self.move(QMouseEvent.globalPos() - self.m_Position) QMouseEvent.accept() def mouseReleaseEvent(self, QMouseEvent): # 鼠标按键释放时,取消移动 self.m_flag = False # 登录事件 def do_login(self): username = self.lineEdit_username.text() password = self.lineEdit_password.text() if not username or not password: QMessageBox.warning(self, '警告', '用户名或密码不能为空', QMessageBox.Yes) return else: IDENTIFIER = self.submit.login(username, password) if not IDENTIFIER: QMessageBox.warning(self, '警告', '用户名或密码错误', QMessageBox.Yes) return self.hide() # 隐藏登录界面 my_submit_form = MySubmitForm(self.submit, IDENTIFIER) my_submit_form.exec_() # 显示主界面
class MySubmitForm(submitform_ui.Ui_Dialog_Submit, QDialog): def __init__(self, submit: TransitSubmit, IDENTIFIER: str): super().__init__() ...... self.setupUi(self) ...... self.progressBar.hide() # 关闭进度条显示 self.setWindowFlags(Qt.FramelessWindowHint) # 无边框 self.setAttribute(Qt.WA_TranslucentBackground) # 设置窗口透明 self.pushButton_mini.clicked.connect(self.showMinimized) # 实现最小化 self.pushButton_close.clicked.connect(self.close) # 实现关闭功能 ...... self.show() # 实现鼠标拖拽功能 def mousePressEvent(self, event): self.pressX = event.x() # 记录鼠标按下的时候的坐标 self.pressY = event.y() def mouseMoveEvent(self, event): x = event.x() y = event.y() # 获取移动后的坐标 moveX = x - self.pressX moveY = y - self.pressY # 计算移动了多少 positionX = self.frameGeometry().x() + moveX positionY = self.frameGeometry().y() + moveY # 计算移动后主窗口在桌面的位置 self.move(positionX, positionY) # 移动主窗口 ......ここでさらに詳しく言わせてください。最初はログインと同じように QFrame を使用しましたが、exec() メソッドがありません。ログイン成功後にポップアップすることはできません。 . 私の知識が限られていてできないこともあるかもしれません。ソースコードを解析した結果、QDialog にはポップアップを実現するためのこのメソッドがあることがわかり、その後、それを変更して QDialog を使用してボーダレス インターフェイスを作成しました。 パッケージングの残りの部分については多くは言いません。インターネット上には多くのチュートリアルがあります。ここで使用するのは、D パッケージ化、upx 圧縮、および変更されたアイコンです。パッケージ化されたプロジェクト全体は 50 以上です。 MB。
以上がPythonでERPシステムデータを自動入力する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。