py_market_data/GET_TDCC_STOCK_DISPERSION.py - GitHub

文章推薦指數: 80 %
投票人數:10人

集保中心~集保戶股權分散表查詢,資料抓取 ... https://stackoverflow.com/questions/2052390/manually-raising-throwing-an-exception-in-python. """ import sqlite3. Skiptocontent {{message}} bryson0083 / py_market_data Public Notifications Fork 0 Star 1 Code Issues 0 Pullrequests 0 Actions Projects 0 Wiki Security Insights More Code Issues Pullrequests Actions Projects Wiki Security Insights Permalink master Branches Tags Couldnotloadbranches Nothingtoshow {{refName}} default Couldnotloadtags Nothingtoshow {{refName}} default py_market_data/GET_TDCC_STOCK_DISPERSION.py / Jumpto DO_WAIT Function CHK_DATA_EXIST Function GET_DATE_LIST Function GET_DATA Function GET_WEB_DATA Function MAIN_GET_TDCC_STOCK_DISPERSION Function Gotofile Gotofile T Gotoline L Gotodefinition R Copypath Copypermalink Thiscommitdoesnotbelongtoanybranchonthisrepository,andmaybelongtoaforkoutsideoftherepository.     Cannotretrievecontributorsatthistime 379lines(317sloc) 12.5KB Raw Blame Editthisfile E OpeninGitHubDesktop OpenwithDesktop Viewraw Viewblame ThisfilecontainsbidirectionalUnicodetextthatmaybeinterpretedorcompileddifferentlythanwhatappearsbelow.Toreview,openthefileinaneditorthatrevealshiddenUnicodecharacters. LearnmoreaboutbidirectionalUnicodecharacters Showhiddencharacters #-*-coding:utf-8-*- """ 集保中心~集保戶股權分散表查詢,資料抓取 @author:BrysonXue @target_rul: 查詢網頁=>https://www.tdcc.com.tw/smWeb/QryStock.jsp @Note: 集保中心~集保戶股權分散表查詢 每日資料結轉寫入資料庫 抓取目標為上市、上櫃股票 @Ref: http://www.largitdata.com/course/53/ https://stackoverflow.com/questions/2052390/manually-raising-throwing-an-exception-in-python """ importsqlite3 importrequests frombs4importBeautifulSoup importpandasaspd importtime fromrandomimportrandint fromdateutilimportparser importdatetime fromdateutil.relativedeltaimportrelativedelta importos.path importsys fromseleniumimportwebdriver fromselenium.webdriver.chrome.optionsimportOptions defDO_WAIT(): #隨機等待一段時間 #sleep_sec=randint(30,120) sleep_sec=randint(5,10) print("間隔等待"+str(sleep_sec)+"secs.") time.sleep(sleep_sec) defCHK_DATA_EXIST(arg_sear_comp_id,arg_quo_date): globalconn #檢查當天該股票是否已有資料 strsql="selectcount(*)fromSTOCK_DISPERSION" strsql+="where" strsql+="QUO_DATE='"+arg_quo_date+"'and" strsql+="SEAR_COMP_ID='"+arg_sear_comp_id+"'" cursor=conn.execute(strsql) result=cursor.fetchone() rows_cnt=result[0] #關閉cursor cursor.close() returnrows_cnt defGET_DATE_LIST(): globalerr_flag globalfile err_cnt=0 #取得日期清單 whileTrue: try: print("抓取日期清單....") #建立網頁讀取 chrome_options=Options() chrome_options.add_argument('--headless') chrome_options.add_argument('--disable-gpu') driver=webdriver.Chrome(chrome_options=chrome_options) #不需要看到執行過程 #driver=webdriver.Chrome()#需要看到執行過程 driver.get("https://www.tdcc.com.tw/smWeb/QryStock.jsp") time.sleep(5) dt_obj=driver.find_element_by_id("scaDates") dt_list=[] forelementindt_obj.find_elements_by_tag_name('option'): dt_list.append(element.text) #關閉瀏覽器視窗 driver.quit() iflen(dt_list)==0: raiseException('Err:Thisisanemptylist.') else: dt_list=sorted(dt_list,reverse=False) print("成功抓取日期清單資料.") break exceptExceptionase: driver.quit() print("讀取日期清單錯誤,等待重新執行...") iferr_cnt==2: err_flag=True print("錯誤次數已達上限,結束本次抓取") print("ErrfromGET_DATE_LIST():\n$$$集保中心網站讀取錯誤,請確認網頁是否正常.$$$\n"+str(e)+"\n") file.write("ErrfromGET_DATE_LIST():\n$$$集保中心網站讀取錯誤,請確認網頁是否正常.$$$\n"+str(e)+"\n") raiseException('錯誤次數已達上限,結束本次抓取') else: print(e.args) print("Errcnt=>"+str(err_cnt)) err_cnt+=1 DO_WAIT() #等待一段時間重新執行 returndt_list defGET_DATA(arg_stock,arg_date): globalerr_flag globalfile #檢查資料庫是否已有資料存在,若已有資料則略過,減少網站讀取 rt_cnt=CHK_DATA_EXIST(arg_stock[0],arg_date) #print("rt_cnt="+str(rt_cnt)) ifrt_cnt==0: #確認資料庫無資料,讀取網頁資料 retry_cnt=0 whileTrue: try: DO_WAIT() #避免過度讀取網站,隨機間隔時間再讀取網頁 rt_flag=GET_WEB_DATA(arg_stock,arg_date) #print("retry_cnt="+str(retry_cnt)+"rt_flag="+str(rt_flag)) ifrt_flag==False: raiseException(str(arg_stock)+"日期"+arg_date+"資料抓取失敗,等待一段時間後,重新抓取.") else: print(str(arg_stock)+"日期"+arg_date+"資料,成功寫入資料庫.") break exceptExceptionase: ifretry_cnt==2: err_flag=True print(str(arg_stock)+"日期"+arg_date+"資料抓取失敗.\n"+str(e.args)+"\n") file.write(str(arg_stock)+"日期"+arg_date+"資料抓取失敗.\n"+str(e.args)+"\n") return else: print("retry_cnt="+str(retry_cnt)) #file.write(str(arg_stock)+"日期"+arg_date+"資料抓取失敗.\n"+str(e.args)+"\n") retry_cnt+=1 else: err_flag=True #print(str(arg_stock)+"日期"+arg_date+"資料已存在,不再重新抓取.\n") #file.write(str(arg_stock)+"日期"+arg_date+"資料已存在,不再重新抓取.\n") defGET_WEB_DATA(arg_stock,arg_date): globalerr_flag globalfile globalconn rt_flag=False sear_comp_id=arg_stock[0] comp_id=arg_stock[0].replace(".TW","") comp_name=arg_stock[1] print("\n抓取"+sear_comp_id+""+comp_name+"日期"+arg_date+"集保戶股權分散資料.") headers={ 'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/68.0.3440.106Safari/537.36'} s=requests.session() payload={ "scaDates":arg_date, "scaDate":arg_date, "SqlMethod":"StockNo", "StockNo":comp_id, "radioStockNo":comp_id, "StockName":"", "REQ_OPR":"SELECT", "clkStockNo":comp_id, "clkStockName":"" } #拋送查詢條件到頁面,並取回查詢結果內容 try: URL='https://www.tdcc.com.tw/smWeb/QryStockAjax.do' r=s.post(URL,data=payload,headers=headers) r.raise_for_status() r.encoding='big5' sp=BeautifulSoup(r.text,'html.parser') exceptExceptionase: err_flag=True print("ErrfromGET_WEB_DATA():\n") print("$$$抓取"+sear_comp_id+""+comp_name+"日期"+arg_date+"集保戶股權分散資料失敗或無資料.$$$\n"+str(e)+"\n") file.write("ErrfromGET_WEB_DATA():\n") file.write("$$$抓取"+sear_comp_id+""+comp_name+"日期"+arg_date+"集保戶股權分散資料失敗或無資料.$$$\n"+str(e)+"\n") raiseException(str(arg_stock)+"日期"+arg_date+"資料抓取失敗,等待一段時間後,重新抓取.GET_WEB_DATASec.1") #若有股票代號是無此資料的,則正常結束跳過此代號 t=r.text #print(t) f_posi=t.find("無此資料") #print("f_posi="+str(f_posi)) iff_posi>0: rt_flag=False print("$$$抓取"+sear_comp_id+""+comp_name+"日期"+arg_date+"集保戶股權分散資料,無此代號資料.$$$\n") file.write("$$$抓取"+sear_comp_id+""+comp_name+"日期"+arg_date+"集保戶股權分散資料,無此代號資料.$$$\n") returnrt_flag tb=sp.select('.mt')[1] all_data=[] fortrintb.select('tr'): rdata=[td.text.replace("\u3000","").replace(",","").strip()fortdintr.select('td')] all_data.append(rdata) ls_head=['SEQ','LV_DESC','NUM_OF_PEOPLE','STOCK_SHARES','PER_CENT_RT'] df=pd.DataFrame(all_data[1:len(all_data)-1],columns=ls_head) #最後一筆合計資料不要 #df=pd.DataFrame(all_data[1:],columns=ls_head) #最後一筆合計資料不要 #插入其他必要欄位 df['QUO_DATE']=arg_date df['SEAR_COMP_ID']=sear_comp_id df['COMP_NAME']=comp_name #最後維護日期時間 str_date=str(datetime.datetime.now()) date_last_maint=parser.parse(str_date).strftime("%Y%m%d") time_last_maint=parser.parse(str_date).strftime("%H%M%S") prog_last_maint="GET_TDCC_STOCK_DISPERSION" df['DATE_LAST_MAINT']=date_last_maint df['TIME_LAST_MAINT']=time_last_maint df['PROG_LAST_MAINT']=prog_last_maint colorder=('QUO_DATE','SEAR_COMP_ID','COMP_NAME','SEQ','LV_DESC','NUM_OF_PEOPLE','STOCK_SHARES','PER_CENT_RT','DATE_LAST_MAINT','TIME_LAST_MAINT','PROG_LAST_MAINT') #df=df.reindex_axis(colorder,axis=1) #調整datagrame欄位順序 http://nullege.com/codes/search/pandas.DataFrame.reindex_axis df=df.reindex(colorder,axis=1) #調整datagrame欄位順序 http://nullege.com/codes/search/pandas.DataFrame.reindex_axis #df.to_sql(name='STOCK_DISPERSION',con=conn,index=False,if_exists='replace') #print(df) #資料寫入資料庫 forindex,rowindf.iterrows(): #print(row['QUO_DATE']+""+row['SEAR_COMP_ID']+""+row['COMP_NAME']+""+row['SEQ']) iflen(row['NUM_OF_PEOPLE'])==0: nop="0" else: nop=row['NUM_OF_PEOPLE'] strsql="insertintoSTOCK_DISPERSION('QUO_DATE','SEAR_COMP_ID','COMP_NAME','SEQ','LV_DESC','NUM_OF_PEOPLE','STOCK_SHARES','PER_CENT_RT','DATE_LAST_MAINT','TIME_LAST_MAINT','PROG_LAST_MAINT')values(" strsql+="'"+row['QUO_DATE']+"'," strsql+="'"+row['SEAR_COMP_ID']+"'," strsql+="'"+row['COMP_NAME']+"'," strsql+=row['SEQ']+"," strsql+="'"+row['LV_DESC']+"'," strsql+=nop+"," strsql+=row['STOCK_SHARES']+"," strsql+=row['PER_CENT_RT']+"," strsql+="'"+row['DATE_LAST_MAINT']+"'," strsql+="'"+row['TIME_LAST_MAINT']+"'," strsql+="'"+row['PROG_LAST_MAINT']+"'" strsql+=")" try: #print(strsql) conn.execute(strsql) conn.commit() rt_flag=True exceptsqlite3.Erroraser: err_flag=True conn.execute("rollback") print("insertSTOCK_DISPERSIONer="+er.args[0]) print(strsql) file.write("insertSTOCK_DISPERSIONer="+er.args[0]+"\n") file.write(strsql+"\n") raiseException(str(arg_stock)+"日期"+arg_date+"資料抓取失敗,等待一段時間後,重新抓取.GET_WEB_DATASec.2") returnrt_flag defMAIN_GET_TDCC_STOCK_DISPERSION(arg_mode='A'): globalerr_flag globalfile globalconn err_flag=False print("Executing"+os.path.basename(__file__)+"...") #LOG檔 str_date=str(datetime.datetime.now()) str_date=parser.parse(str_date).strftime("%Y%m%d") name="GET_TDCC_STOCK_DISPERSION_LOG_"+str_date+".txt" file=open(name,"a",encoding="UTF-8") print_dt=str(str_date)+(''*22) print("##############################################") print("##集保戶股權分散表查詢##") print("##(上市、上櫃股票)##") print("####") print("##datetime:"+print_dt+"##") print("##############################################") tStart=time.time()#計時開始 file.write("\n\n\n***LOGdatetime"+str(datetime.datetime.now())+"***\n") file.write("Executing"+os.path.basename(__file__)+"...\n") #依據所選模式,決定抓取方式 #modeA:抓取最近一周資料 #modeB:抓取日期清單所有資料 try: #run_mode=sys.argv[1] run_mode=arg_mode run_mode=run_mode.upper() exceptExceptionase: run_mode="A" print("youchoosemode"+run_mode) ifrun_mode=="A": print("選取模式A:抓取最近一周資料...\n") file.write("選取模式A:抓取最近一周資料...\n") elifrun_mode=="B": print("選取模式B:抓取日期清單所有資料...\n") file.write("選取模式B:抓取日期清單所有資料...\n") else: print("模式錯誤,結束程式...\n") file.write("模式錯誤,結束程式...\n") sys.exit("模式錯誤,結束程式...\n") #建立資料庫連線 conn=sqlite3.connect("market_price.sqlite") #抓取網站日期清單 try: dt_list=GET_DATE_LIST() #print(dt_list) exceptExceptionase: print("抓取日期清單失敗...") print(e.args) #dt_list=['20180817'] #fortest手動用 ifrun_mode=="A": dt_list=dt_list[-1:] #print(dt_list) iferr_flag==False: fordtindt_list: str_date=str(dt) #讀取上市櫃股票清單 strsql="selectSTOCK_COMP_LIST.SEAR_COMP_ID,STOCK_COMP_LIST.COMP_NAME,STOCK_COMP_LIST.STOCK_TYPEfromSTOCK_COMP_LIST" strsql+="LEFTJOINTDCC_IGNRonTDCC_IGNR.SEAR_COMP_ID=STOCK_COMP_LIST.SEAR_COMP_ID" strsql+="where" #strsql+="STOCK_COMP_LIST.SEAR_COMP_ID='0050.TW'and" strsql+="STOCK_COMP_LIST.IPO_DATE<='"+str_date+"'and" strsql+="TDCC_IGNR.SEAR_COMP_IDisNULL" strsql+="orderbySTOCK_COMP_LIST.STOCK_TYPE,STOCK_COMP_LIST.SEAR_COMP_ID" #strsql+="limit1" cursor=conn.execute(strsql) result=cursor.fetchall() #關閉cursor cursor.close() iflen(result)>0: forstockinresult: GET_DATA(stock,str_date) else: err_flag=True print("$$$未取得公司清單資料.$$$") file.write("$$$未取得公司清單資料.$$$") tEnd=time.time()#計時結束 file.write("\n\n\n結轉耗時%fsec\n"%(tEnd-tStart))#會自動做進位 file.write("***EndLOG***\n") #CloseFile file.close() #關閉資料庫連線 conn.close() #若執行過程無錯誤,執行結束後刪除log檔案 iferr_flag==False: os.remove(name) print("\n\n集保中心~集保戶股權分散表查詢,資料抓取結束...\n\n\n") if__name__=='__main__': MAIN_GET_TDCC_STOCK_DISPERSION() Copylines Copypermalink Viewgitblame Referenceinnewissue Go Youcan’tperformthatactionatthistime. Yousignedinwithanothertaborwindow.Reloadtorefreshyoursession. Yousignedoutinanothertaborwindow.Reloadtorefreshyoursession.



請為這篇文章評分?