一、目標(biāo)分析
1.1 目標(biāo)系統(tǒng)
系統(tǒng)版本:SAP系統(tǒng)NetWeaver。SRM主要功能如下圖,其中需求預(yù)測(cè)、采購(gòu)執(zhí)行監(jiān)控、寄售庫(kù)存監(jiān)控是業(yè)務(wù)計(jì)劃有關(guān)的數(shù)據(jù),使用頻率最高。
?數(shù)據(jù)采集范圍
?SAP/SRM系統(tǒng)界面
1.2 業(yè)務(wù)痛點(diǎn)
對(duì)于使用SRM的供應(yīng)商來(lái)說(shuō),他們頻繁登錄SRM系統(tǒng)多有不便,SRM數(shù)據(jù)無(wú)法與自己公司信息系統(tǒng)對(duì)接,導(dǎo)致業(yè)務(wù)溝通不暢。
?
業(yè)務(wù)痛點(diǎn)分析
1.3 業(yè)務(wù)訴求
對(duì)于供應(yīng)商來(lái)說(shuō),希望采集SAP-SRM數(shù)據(jù),存入數(shù)據(jù)庫(kù),建立業(yè)務(wù)模型,實(shí)現(xiàn)客戶計(jì)劃、生產(chǎn)計(jì)劃、庫(kù)存占用之間的數(shù)據(jù)聯(lián)動(dòng),從而提高效率,降低成本。
?數(shù)據(jù)方面的訴求
1.4 采集方法
大家問(wèn):為何要采用模擬采集?
工程師答:經(jīng)過(guò)我們測(cè)試分析,該系統(tǒng)對(duì)應(yīng)頁(yè)面數(shù)據(jù)結(jié)構(gòu)復(fù)雜,采用數(shù)據(jù)動(dòng)態(tài)加載,普通采集工具只能采集10條,即便是滾動(dòng)鼠標(biāo)循環(huán)獲取分頁(yè)也無(wú)法采集全部數(shù)據(jù),且數(shù)據(jù)較多時(shí)分頁(yè)獲取數(shù)據(jù)速度非常慢。
方案定制:需求的數(shù)據(jù)可以通過(guò)調(diào)整業(yè)務(wù)參數(shù),點(diǎn)擊查詢加載數(shù)據(jù),數(shù)據(jù)加載后,導(dǎo)出Excel即可獲取原始數(shù)據(jù)。
二、程序功能
?爬蟲(chóng)定制程序5大功能
網(wǎng)絡(luò)爬蟲(chóng),數(shù)據(jù)采集程序,不僅僅是采集數(shù)據(jù),還要實(shí)現(xiàn)數(shù)據(jù)清洗、數(shù)據(jù)加工,數(shù)據(jù)對(duì)比分析,數(shù)據(jù)存儲(chǔ)。數(shù)據(jù)采集程序可以按需運(yùn)行,也可以按指定頻率運(yùn)行。新增業(yè)務(wù)數(shù)據(jù)可以通過(guò)企業(yè)微信進(jìn)行提醒。
三、程序框架
3.1 工程目錄
數(shù)采程序工程目錄
1、文件夾P10-P50:用于存放采集程序工作期間產(chǎn)生的文件;P90-logs:用于存放程序工作期間運(yùn)行日志
2、DataSyn_xxx.py采集程序入口文件,在此文件中定義了數(shù)據(jù)處理需要經(jīng)歷的步驟(后面附有詳細(xì)代碼)
3、Logger.py程序日志模塊
4、企業(yè)wx_xxx.py,qywx模塊,用于發(fā)送消息提醒和文件附件
5、數(shù)據(jù)庫(kù)ORM_xxx.py,對(duì)象實(shí)體映射,用于保存數(shù)據(jù)到數(shù)據(jù)庫(kù)
6、文件P10-P50,數(shù)據(jù)處理模塊,用于數(shù)據(jù)各階段的分段處理,會(huì)被主程序DataSyn_xxx.py調(diào)用執(zhí)行,從而完成各種功能
7、sysconfig.ini,存放WEB/DB的配置信息,服務(wù)器地址、用戶名、密碼
3.2 程序代碼
import os
import time
from P10數(shù)據(jù)采集_cnhtc import GetWebData
from P20數(shù)據(jù)清洗_cnhtc import DataCleaning
from P30差異分析_cnhtc import DataDis
from P50業(yè)務(wù)提醒_cnhtc import SendMsg
from 企業(yè)微信_(tái)cnhtc import wx
from Logger import Logging
from SpiderManager.AppList import *
class cnhtcerp:
def __init__(self, msg_url=None):
# 程序名稱
appCode = os.path.split(os.path.abspath(__file__))[0].split("\\")[-1] # 上級(jí)目錄名稱
self.AppName = applist[appCode]
self.logger = Logging().log(level='INFO')
if not (app_run_start_time <= time.strftime("%H:%M", time.localtime()) <= app_run_end_time):
self.logger.warning(
"程序【{}】不在預(yù)設(shè)運(yùn)行時(shí)段[{}]-[{}],程序結(jié)束!\n\n\n".format(self.AppName, app_run_start_time, app_run_end_time))
return
self.logger.info("程序:{},開(kāi)始運(yùn)行 ... ".format(self.AppName))
# 各階段文件夾
self.msg_url = msg_url
self.DirName = {'P10': "P10-源數(shù)據(jù)", 'P20': "P20-數(shù)據(jù)清洗",
'P30': "P30-差異分析", 'P40': "P40-數(shù)據(jù)存儲(chǔ)", 'P50': "P50-更新提醒"}
self.curPath = os.getcwd()
self.logger.info("當(dāng)前程序工作目錄:{}".format(self.curPath))
s = wx()
try:
self.__RunApp()
except Exception as err:
err_msg = "程序出錯(cuò)提示!\n[系統(tǒng)名稱:{}]:\n{}".format(self.AppName, err)
self.logger.info(err_msg)
s.send_text(err_msg, "MaLaoShi")
self.logger.error("程序執(zhí)行遇到錯(cuò)誤!程序退出!\n\n\n")
exit()
def __RunApp(self):
self.__檢查文件目錄()
self.__數(shù)據(jù)采集()
self.__數(shù)據(jù)清洗()
self.__差異分析()
self.__業(yè)務(wù)提醒()
self.logger.info("程序結(jié)束\n{}\n\n\n".format("=" * 90))
def __檢查文件目錄(self):
for x in self.DirName.values():
if not (os.path.exists(os.path.join(x))):
os.mkdir(os.path.join(x))
self.logger.info("創(chuàng)建{}目錄!".format(x))
def __數(shù)據(jù)采集(self):
AppName = "__數(shù)據(jù)采集"
FilePath = self.DirName['P10']
Dir = os.path.join(self.curPath, FilePath)
self.logger.info("程序:{},開(kāi)始運(yùn)行 ... ".format(AppName))
self.logger.info("程序工作文件夾:{}".format(Dir))
GetWebData(Dir)
def __數(shù)據(jù)清洗(self):
AppName = "__數(shù)據(jù)清洗"
FilePath1 = self.DirName['P10'] # 源數(shù)據(jù)文件路徑
FilePath2 = self.DirName['P20'] # 目標(biāo)數(shù)據(jù)文件路徑
Dir1 = os.path.join(self.curPath, FilePath1)
Dir2 = os.path.join(self.curPath, FilePath2)
self.logger.info("程序:{},開(kāi)始運(yùn)行 ... ".format(AppName))
self.logger.info("源數(shù)據(jù)文件路徑:{}".format(Dir1))
self.logger.info("目標(biāo)據(jù)文件路徑:{}".format(Dir2))
DataCleaning(Dir1, Dir2)
def __差異分析(self):
AppName = "__差異分析"
FilePath1 = self.DirName['P20'] # 源數(shù)據(jù)文件路徑
FilePath2 = self.DirName['P30'] # 分析數(shù)據(jù)文件路徑
Dir1 = os.path.join(self.curPath, FilePath1)
Dir2 = os.path.join(self.curPath, FilePath2)
self.logger.info("程序:{},開(kāi)始運(yùn)行 ... ".format(AppName))
self.logger.info("源數(shù)據(jù)文件路徑:{}".format(Dir1))
self.logger.info("分析數(shù)據(jù)文件路徑:{}".format(Dir2))
DataDis(Dir1, Dir2)
def __業(yè)務(wù)提醒(self):
AppName = "__業(yè)務(wù)提醒"
FilePath1 = self.DirName['P30'] # 源數(shù)據(jù)文件路徑
FilePath2 = self.DirName['P50'] # 分析數(shù)據(jù)文件路徑
Dir1 = os.path.join(self.curPath, FilePath1)
Dir2 = os.path.join(self.curPath, FilePath2)
self.logger.info("程序:{},開(kāi)始運(yùn)行 ... ".format(AppName))
self.logger.info("源數(shù)據(jù)文件路徑:{}".format(Dir1))
self.logger.info("目標(biāo)數(shù)據(jù)文件路徑:{}".format(Dir2))
if self.msg_url is not None:
qywx_url = self.msg_url
else:
qywx_url = 'qywxURL'
# 按時(shí)段發(fā)送消息提醒
if msg_run_start_time <= time.strftime("%H:%M", time.localtime()) <= msg_run_end_time:
self.logger.info("提醒時(shí)段,發(fā)送消息!")
s = SendMsg(Dir1, Dir2)
s.send_qywx(qywx_url)
else:
self.logger.info("非提醒時(shí)段,不發(fā)送消息!")
if __name__ == "__main__":
msg_url = 'qywxURL'
cnhtcerp()
3.3 代碼解析
1、DataSyn的核心意義就是數(shù)據(jù)采集、數(shù)據(jù)同步。在這個(gè)模塊中調(diào)用了其他功能模塊,分塊實(shí)現(xiàn)了爬蟲(chóng)程序的各個(gè)功能,各個(gè)模塊既獨(dú)立又相互銜接
2、【__init__】方法:
(1)判斷當(dāng)前時(shí)間是否在允許的運(yùn)行時(shí)間內(nèi),如果在允許運(yùn)行時(shí)段內(nèi)繼續(xù)運(yùn)行程序,否則不在運(yùn)行。
(2)調(diào)用了【__RunApp】方法進(jìn)行數(shù)據(jù)處理。同時(shí),進(jìn)行了錯(cuò)誤捕捉,程序執(zhí)行錯(cuò)誤會(huì)通過(guò)企業(yè)微信通知管理人員。管理人員結(jié)合報(bào)錯(cuò)提示信息、報(bào)錯(cuò)時(shí)間點(diǎn)、程序工作日志,分析報(bào)錯(cuò)原因,改進(jìn)采集程序。
3、【__RunApp】方法
將調(diào)用所有的數(shù)據(jù)處理程序
4、【__檢查文件目錄】方法
檢查程序運(yùn)行需要的文件夾是否存在,不存在就創(chuàng)建
5、【__數(shù)據(jù)采集】方法
調(diào)用數(shù)據(jù)采集程序,保存原始數(shù)據(jù)到指定目錄(P10文件夾)
6、【__數(shù)據(jù)清洗】方法
調(diào)用數(shù)據(jù)清洗程序,從P10文件夾獲取數(shù)據(jù),數(shù)據(jù)清洗、數(shù)據(jù)加工完畢后存入P20文件夾
7、【__差異分析】方法
調(diào)用數(shù)據(jù)差異分析程序,從P20文件夾獲取數(shù)據(jù)、從data in DB中獲取數(shù)據(jù),兩方面數(shù)據(jù)對(duì)比分析出差異,將采集數(shù)據(jù)每一條記錄進(jìn)行標(biāo)記(新增、修改、作廢、不修改)。差異分析完畢后調(diào)用數(shù)據(jù)存儲(chǔ)程序進(jìn)行數(shù)據(jù)保存。
8、【__業(yè)務(wù)提醒】方法
調(diào)用提醒程序,發(fā)送qywx文字消息和文件。
四、數(shù)據(jù)采集
4.1 程序代碼
import os
import time
import datetime
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.options import Options
import json
from Logger import Logging
import shutil
class GetWebData:
def __init__(self, Dir):
self.Dir = Dir
self.logger = Logging().log(level="INFO")
self.__reset_fileDir()
self.curPath = os.getcwd()
self.is_headless = 0
try_times = 1
while True:
self.logger.info("進(jìn)行第 {} 次數(shù)據(jù)采集 ... ".format(try_times))
files_count = self.__RunApp()
if files_count == 3:
self.logger.info("采集數(shù)據(jù)成功!程序繼續(xù)...")
return
else:
self.logger.info("采集數(shù)據(jù)失??!")
try_times += 1
time.sleep(30)
continue
if try_times > 3:
raise "數(shù)據(jù)采集失敗,超過(guò)3次!"
def __reset_fileDir(self):
dl_path = self.Dir
self.logger.info("檢查文件夾狀態(tài) ... ")
if os.path.exists(dl_path):
self.logger.info("存在文件夾!")
files = os.listdir(dl_path)
file_count = len(files)
if file_count > 0:
self.logger.info("文件夾存在文件,文件數(shù)量:{}".format(file_count))
shutil.rmtree(dl_path)
self.logger.info("刪除文件夾!")
# 創(chuàng)建文件夾
os.mkdir(dl_path)
self.logger.info("創(chuàng)建文件夾!")
else:
# 創(chuàng)建文件夾
os.mkdir(dl_path)
self.logger.info("創(chuàng)建文件夾!")
time.sleep(1)
return True
def __RunApp(self):
self.logger.info("程序名稱:{} ".format("get_web_data"))
ts = time.time()
with open(os.path.join(self.curPath, "sysconfig.ini"), "r") as f:
info = json.loads(f.read())
url = info['app_host']
userName = info['app_user']
password = info['app_pwd']
# 設(shè)置options:文件下載路徑
options = Options()
prefs = {
'profile.default_content_settings.popups': 0,
'download.default_directory': self.Dir,
}
options.add_experimental_option('prefs', prefs)
if self.is_headless == 1:
# 無(wú)窗口運(yùn)行模式
options.add_argument('--headless')
self.logger.info("設(shè)置文件下載路徑!")
self.driver = webdriver.Chrome(options=options) # 啟動(dòng)瀏覽器!
self.driver.set_window_size(1466, 1000)
# self.driver.maximize_window() # 窗口最大化!
self.driver.get(url) # 輸入網(wǎng)址!
time.sleep(3)
self.logger.info("輸入用戶名和密碼 ... ")
self.driver.find_element(By.ID, "sap-user").send_keys(userName)
self.driver.find_element(By.ID, "sap-password").send_keys(password)
self.driver.find_element(By.ID, "LOGON_BUTTON").click()
self.logger.info("登錄系統(tǒng)!")
self.__cancel_other_login() # 檢測(cè)多余登錄并處理
self.__get_預(yù)測(cè)訂單查詢()
self.__get_庫(kù)存查詢()
self.__get_采購(gòu)訂單執(zhí)行監(jiān)控查詢()
self.__quit_system()
te = time.time()
self.logger.info("數(shù)據(jù)獲取完成,耗時(shí): {} s".format(round(te - ts)))
files_count = len(os.listdir(self.Dir))
return files_count
def __cancel_other_login(self):
self.logger.info("程序名稱:{}".format("__cancel_other_login"))
try:
e = self.driver.find_element(By.ID, 'SESSION_QUERY_CONTINUE_BUTTON')
ActionChains(self.driver).move_to_element(e).pause(0.1).perform()
ActionChains(self.driver).click(e).perform()
self.logger.warning("識(shí)別重復(fù)登錄:selenium點(diǎn)擊繼續(xù)登錄!")
except Exception as err:
self.logger.info("未發(fā)現(xiàn)重復(fù)登錄:{}")
def __get_預(yù)測(cè)訂單查詢(self):
time.sleep(2)
e1 = self.driver.find_element(By.LINK_TEXT, "需求預(yù)測(cè)")
ActionChains(self.driver).move_to_element(e1).pause(0.1).perform()
ActionChains(self.driver).click(e1).perform()
self.logger.info("點(diǎn)擊按鈕,需求預(yù)測(cè)!")
time.sleep(2)
self.driver.switch_to.frame(0)
self.logger.info("進(jìn)入iFrame")
time.sleep(2)
date_60 = datetime.datetime.today() + datetime.timedelta(days=1) * 60
date_60_str = date_60.strftime("%Y-%m-%d")
e_date = self.driver.find_element(By.XPATH, '//*[@id="WD7D"]')
e_date.clear()
e_date.send_keys(date_60_str)
self.logger.info("設(shè)置查詢截止日期—60天后!")
e2 = self.driver.find_element(By.ID, "WD85-caption")
ActionChains(self.driver).move_to_element(e2).pause(0.1).perform()
ActionChains(self.driver).click(e2).perform()
self.logger.info("點(diǎn)擊按鈕,查詢按鈕!")
time.sleep(2)
e2 = self.driver.find_element(By.ID, "WDA9-cnt")
ActionChains(self.driver).move_to_element(e2).pause(0.1).perform()
ActionChains(self.driver).click(e2).perform()
self.logger.info("點(diǎn)擊按鈕,導(dǎo)出按鈕!")
time.sleep(0.2)
ActionChains(self.driver).move_by_offset(0, 20).click().perform()
self.logger.info("點(diǎn)擊按鈕,導(dǎo)出Excel文件!")
self.driver.switch_to.parent_frame()
def __get_庫(kù)存查詢(self):
time.sleep(2)
try:
e0 = self.driver.find_element(By.XPATH, "/html/body/div/div[2]/div/ul/li[1]")
ActionChains(self.driver).move_to_element(e0).pause(0.1).perform()
ActionChains(self.driver).click(e0).perform()
self.logger.info("屏幕太小,訂單菜單顯示不全處理!")
except Exception as err:
self.logger.info("沒(méi)有發(fā)現(xiàn)滾動(dòng)條:{}".format(err))
e1 = self.driver.find_element(By.LINK_TEXT, "寄售庫(kù)存監(jiān)控")
ActionChains(self.driver).move_to_element(e1).pause(0.1).perform()
ActionChains(self.driver).click(e1).perform()
self.logger.info("點(diǎn)擊按鈕,需求預(yù)測(cè)!")
time.sleep(2)
self.driver.switch_to.frame(0)
self.logger.info("進(jìn)入iFrame")
time.sleep(2)
e2 = self.driver.find_element(By.ID, "WD76-caption")
ActionChains(self.driver).move_to_element(e2).pause(0.1).perform()
ActionChains(self.driver).click(e2).perform()
self.logger.info("點(diǎn)擊按鈕,查詢按鈕!")
time.sleep(3)
e2 = self.driver.find_element(By.ID, "WD9A-cnt")
ActionChains(self.driver).move_to_element(e2).pause(0.1).perform()
ActionChains(self.driver).click(e2).perform()
self.logger.info("點(diǎn)擊按鈕,導(dǎo)出按鈕!")
time.sleep(0.2)
ActionChains(self.driver).move_by_offset(0, 20).click().perform()
self.logger.info("點(diǎn)擊按鈕,導(dǎo)出Excel文件!")
self.driver.switch_to.parent_frame()
def __get_采購(gòu)訂單執(zhí)行監(jiān)控查詢(self):
time.sleep(2)
try:
e0 = self.driver.find_element(By.XPATH, "/html/body/div/div[2]/div/ul/li[1]")
ActionChains(self.driver).move_to_element(e0).pause(0.1).perform()
ActionChains(self.driver).click(e0).perform()
self.logger.info("屏幕太小,訂單菜單顯示不全處理!")
except Exception as err:
self.logger.info("沒(méi)有發(fā)現(xiàn)滾動(dòng)條:{}".format(err))
e1 = self.driver.find_element(By.LINK_TEXT, "采購(gòu)執(zhí)行監(jiān)控")
ActionChains(self.driver).move_to_element(e1).pause(0.1).perform()
ActionChains(self.driver).click(e1).perform()
self.logger.info("點(diǎn)擊按鈕,采購(gòu)執(zhí)行監(jiān)控!")
time.sleep(2)
self.driver.switch_to.frame(0)
time.sleep(2)
self.logger.info("進(jìn)入iFrame")
date_x = datetime.datetime.today() - datetime.timedelta(days=1) * 30 * 3
date_x_set = date_x.strftime("%Y-%m-%d")
s_date = self.driver.find_element(By.XPATH, '//*[@id="WD53"]')
s_date.clear()
s_date.send_keys(date_x_set)
e2 = self.driver.find_element(By.ID, "WD8F-cnt")
ActionChains(self.driver).move_to_element(e2).pause(0.1).perform()
ActionChains(self.driver).click(e2).perform()
self.logger.info("點(diǎn)擊按鈕,查詢按鈕!")
ts = time.time()
while True:
try:
el_path = '/html/body/table/tbody/tr/td/div/div[1]/table/tbody/tr[2]/td/table/tbody/tr/td/div/div/table/tbody/tr[2]/td/div/table/tbody/tr/td/table/tbody/tr[1]/td/table/tbody/tr/td/div/div/span[2]'
el_find = self.driver.find_element(By.XPATH, el_path)
if '查詢結(jié)果:' in el_find.text:
self.logger.info("查詢完成,耗時(shí):{} s".format(round(time.time() - ts, 2)))
break
except:
self.logger.info("查詢等待 ... ")
time.sleep(2)
if time.time() - ts > 60:
self.logger.warning("查詢超時(shí)(60秒),退出程序!el_path:{}".format(el_path))
break
e2 = self.driver.find_element(By.ID, "WDB3-cnt")
ActionChains(self.driver).move_to_element(e2).pause(0.1).perform()
ActionChains(self.driver).click(e2).perform()
self.logger.info("點(diǎn)擊按鈕,導(dǎo)出按鈕!")
ActionChains(self.driver).move_by_offset(0, 20).click().perform()
self.logger.info("點(diǎn)擊按鈕,導(dǎo)出Excel文件!")
self.driver.switch_to.parent_frame()
time.sleep(4)
def __quit_system(self):
time.sleep(2)
logoff = self.driver.find_element(By.ID, "logoff_link")
ActionChains(self.driver).move_to_element(logoff).click().perform()
self.logger.info("點(diǎn)擊按鈕,注銷登錄!")
time.sleep(1)
self.driver.switch_to.frame(1)
self.logger.info("進(jìn)入iFrame1")
confirm = self.driver.find_element(By.XPATH, "/html/body/div[2]/div[5]/ul/li[1]/div[2]")
ActionChains(self.driver).move_to_element(confirm).click().perform()
self.logger.info("點(diǎn)擊按鈕,確定注銷登錄!")
time.sleep(2)
self.driver.quit()
self.logger.info("關(guān)閉瀏覽器!")
if __name__ == "__main__":
ts = time.time()
Dir = 'C:\Python\pydoc\cnhtcerp\P10-源數(shù)據(jù)'
s = GetWebData(Dir)
te = time.time()
print("執(zhí)行完成!耗時(shí):{} s".format(round(te - ts, 2)))
4.2 代碼解析
1、【__init__】方法
在此方法中運(yùn)行【__RunApp】方法,程序開(kāi)始采集數(shù)據(jù),采集成功后將原始數(shù)據(jù)保存到指定文件,通過(guò)判斷采集文件個(gè)數(shù)來(lái)確定數(shù)據(jù)是否全部采集成功。如果未全部采集成功,將繼續(xù)運(yùn)行采集程序。運(yùn)行3次后無(wú)法采集成功時(shí),程序報(bào)錯(cuò),通過(guò)qywx通知管理員。
2、【__reset_fileDir】方法,重設(shè)文件夾,主要是查看指定文件夾是否為空,不為空則清空。
3、【__RunApp】方法,在此方法中,使用Chrome瀏覽器,登錄目標(biāo)系統(tǒng),采集數(shù)據(jù),注銷登錄,關(guān)閉瀏覽器。
4、【__cancel_other_login】方法,檢測(cè)是否存在重復(fù)登錄,如果存在繼續(xù)本次登錄,注銷其他登錄。
5、【__get_預(yù)測(cè)訂單查詢】、【__get_庫(kù)存查詢】、【__get_采購(gòu)訂單執(zhí)行監(jiān)控查詢】方法,用于采集具體頁(yè)面數(shù)據(jù)。由于查詢?nèi)掌诳缍却?,?shù)據(jù)量大,加載時(shí)間長(zhǎng),因網(wǎng)絡(luò)不同而已,所以在【__get_采購(gòu)訂單執(zhí)行監(jiān)控查詢】方法中檢測(cè)頁(yè)面數(shù)據(jù)是否加載完畢,加載完畢則可導(dǎo)出數(shù)據(jù),否則繼續(xù)等待頁(yè)面加載完成,超過(guò)60秒未加載完成退出本方法。 6、【__quit_system】方法,注銷登錄,退出瀏覽器。
五、運(yùn)行結(jié)果
5.1 采集數(shù)據(jù)同步到數(shù)據(jù)庫(kù)
程序按預(yù)設(shè)頻率定時(shí)運(yùn)行,原始數(shù)據(jù)采集后,經(jīng)過(guò)數(shù)據(jù)清洗,差異對(duì)比分析,最后將數(shù)據(jù)增量寫入數(shù)據(jù)庫(kù)中。
?采集數(shù)據(jù)存入數(shù)據(jù)庫(kù)中
5.2 業(yè)務(wù)提醒
業(yè)務(wù)數(shù)據(jù)有更新時(shí)發(fā)送qywx提醒,讓業(yè)務(wù)相關(guān)人員做到心中有數(shù),業(yè)務(wù)開(kāi)展,計(jì)劃調(diào)整,胸有成竹。
業(yè)務(wù)提醒
5.3 業(yè)務(wù)模型建立
采集數(shù)據(jù)不是目的,如何最大化利用數(shù)據(jù),發(fā)揮數(shù)據(jù)價(jià)值才是最終目的。本案例利用采集數(shù)據(jù),建立庫(kù)存當(dāng)量(最低庫(kù)存、最高庫(kù)存),結(jié)合ERP存貨現(xiàn)存量、采購(gòu)在途量、生產(chǎn)訂單在制量等數(shù)據(jù),計(jì)算該存貨在該時(shí)點(diǎn)的最小/最大可入庫(kù)量。利用報(bào)表工具,將計(jì)劃數(shù)據(jù)共享給生產(chǎn)、采購(gòu)、營(yíng)銷等部門,指導(dǎo)生產(chǎn)、采購(gòu)、營(yíng)銷協(xié)同工作,因?yàn)閹?kù)存當(dāng)量動(dòng)態(tài)調(diào)整,所以庫(kù)存占用趨于合理化,相比以前存貨占用下降了30%,交付效率提高了20%。
5.4 視頻演示文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-656529.html
數(shù)據(jù)采集視頻文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-656529.html
到了這里,關(guān)于Python爬蟲(chóng)/SAP-SRM數(shù)據(jù)采集的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!