返回列表 上一主題 發帖

python 融資融券彙總 (全部)"資料

本帖最後由 lpk187 於 2016-9-29 09:33 編輯

回復 30# c_c_lai

剛測試了一下,在Jupyther Notebook 上執行。
執行後沒錯誤產生,但卻是沒有資料存進去,
但一般執行卻沒有問題。
你試試一般執行,看結果如何
融資融券彙總SQLite3.rar (3.07 KB)

TOP

應該是不會有導入資料的問題,颱風天小弟就把sqlite3從0~500MB了
其中會發生錯誤沒錯,有時是網頁資料格式不一,有時是網頁資料空格,不然就是多了什麼文字讓循環錯誤(字串的處理很重要,大都錯在這個,加個判別式即可)
記得同一資料庫(就算是不同表格),不要用2支程式跑
Sqlite3好像處理會來不及,程式就中斷了
以上是小弟的個人經驗~
PS:小弟用Jupyter 跑的

TOP

本帖最後由 lpk187 於 2016-9-29 12:53 編輯

回復 30# c_c_lai

一個很奇怪的問題,我也搞不懂!
以下面這段程式碼來說,照理說,當
try:
       c = conn.cursor()
       sql="SELECT * FROM [" + regs[0] + "] WHERE 日期 = '" + date + "';"
       c.execute(sql)
       c.close()
找不到此日期,應該會產生錯誤,傳給except Exception as e: 執行才對,但
在Jupyter NoteBook 卻是不會產生錯誤(以一般的pyhton 會傳回錯誤訊息)
我試著去SQLiteStudio中打上檢詢錯誤的日期,雖然找不到,但也沒有產生錯誤,
所以我改了程式碼,你試看看,請複製以下代碼
其中也修正擷取網路資料的迴圈,現在擷取變很快
  1. #-*- coding:utf-8 -*-
  2. import requests
  3. from bs4 import BeautifulSoup
  4. import random
  5. import os
  6. import sqlite3
  7. import datetime
  8. import time

  9. # 隨機更改 headers
  10. def head_random():
  11.     for i in range(10):
  12.             hs = ['Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
  13.                    'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16',
  14.                    'Mozilla/5.0 (Linux; U; Android 4.1.2; zh-tw; GT-I9300 Build/JZO54K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30',
  15.                    'Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10'
  16.                    'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)']
  17.             hes = {"User-Agent":random.choice(hs)}
  18.     return hes

  19. # 集台證所融資融券餘額全部資料
  20. def read_network_data(date,from_number):
  21.     url = 'http://www.twse.com.tw/ch/trading/exchange/MI_MARGN/MI_MARGN.php'
  22.     head =head_random()
  23.     payload = {"download":'',
  24.             "qdate":date,
  25.             "selectType":"ALL"}
  26.     res = requests.post(url, headers=head, data=payload)
  27.     soup=BeautifulSoup(res.text, "lxml")
  28.     tab = soup.select('tbody')[from_number] # 2個表格之2
  29.     regs=[] # 初始陣列
  30.       
  31.     le=len(tab.select('tr')[0].select('td'))
  32.     for i in range(le): # 定義2維陣列維度
  33.         regs.append([])
  34.     for tr in tab.select('tr'): #擷取表格資料
  35.         for i in range(le):
  36.             if i==0 or i==1 or i==15:      #把文字串中的空白文字去除掉
  37.                 strs=tr.select('td')[i].text
  38.                 strs=str(strs.replace(' ',''))
  39.                 regs[i].append(strs)
  40.             else:    # 把數字中的千分符號 "," 去除掉
  41.                 ints=tr.select('td')[i].text
  42.                 ints=str(ints.replace(',',''))
  43.                 regs[i].append(ints)
  44.     return regs

  45. def check_db_exists(regs):
  46.     if not os.path.exists('twsedata.db'):   # 檢查twsedata.db是否存在(和此程式碼相同的資料夾)
  47.         conn = sqlite3.connect('twsedata.db')  # 如果沒有,就建立一個空白資料庫,(sqlite3.connect) 也是連結語句,有資料庫就連結,沒有就建立
  48.         sql = "CREATE TABLE 股票(股票代號  char(10) PRIMARY KEY,股票名稱  char(20));"
  49.         conn.execute(sql) #在新資料庫建立空白資料表 (股票)
  50.         sql = "CREATE TABLE  融資融券信用交易統計( \
  51.                                 日期  datetime, \
  52.                                 項目  char(20), \
  53.                                 買進 INTEGER, \
  54.                                 買出 INTEGER, \
  55.                                 現金(券)償還 INTEGER, \
  56.                                 前日餘額 INTEGER, \
  57.                                 今日餘額 INTEGER);"
  58.         conn.execute(sql) #在新資料建立 空白資料表(融資融券信用交易統計)
  59.         conn.commit() # 儲存
  60.         conn.close() #關閉
  61.             
  62.     n=0
  63.     conn = sqlite3.connect('twsedata.db') # conn和上一個 if ..中的 conn是不一樣的 ,上一個是沒有資料庫時才作用,為局部變數而此處,則為以下使用的全局變數
  64.     for i in regs[0]:  #以爬回來的資料陣列的第一列為迴圈
  65.         try:      #先嘗試查詢 i 變數的資料表是否存在,若是不存在會發出 Exception 的錯誤訊息
  66.             c = conn.cursor()
  67.             sql = "select * from [" + i + "]"
  68.             c.execute(sql) # table does not exist
  69.             c.close()
  70.         except Exception as e:  #當try 發出錯誤訊息(也就是讀不到  i 資料表),此時建立一個 i 資料表
  71.             c = conn.cursor()
  72.             sql="CREATE TABLE [" + i + "](日期  DATETIME PRIMARY KEY, \
  73.                                         資買進  INTEGER, \
  74.                                         資賣出 INTEGER, \
  75.                                         資現金償還 INTEGER, \
  76.                                         資前日餘額 INTEGER, \
  77.                                         資今日餘額 INTEGER, \
  78.                                         資限額 INTEGER, \
  79.                                         券買進  INTEGER, \
  80.                                         券賣出 INTEGER, \
  81.                                         券現金償還 INTEGER, \
  82.                                         券前日餘額 INTEGER, \
  83.                                         券今日餘額 INTEGER, \
  84.                                         券限額 INTEGER, \
  85.                                         資券互抵 INTEGER, \
  86.                                         註記 char(5));"
  87.             c.execute(sql) #建立 i 資料表
  88.             sql="INSERT INTO 股票(股票代號, 股票名稱) \
  89.                 VALUES ('" + regs[0][n] + "','" + regs[1][n] + "');"
  90.             c.execute(sql)  # 在股票資料表中寫入股票代號、股票名稱
  91.             c.close() # 關閉 c 物件
  92.         n += 1
  93.     conn.commit()
  94.     conn.close()
  95. def add_data(regs,date):
  96.     conn = sqlite3.connect('twsedata.db')
  97.     for i in range(len(regs[0])):
  98.         try: #檢查某日期是否存在於資料表中,當某日期存在時,跳離這次的循環,這裡指的僅是這次,不是跳離 for
  99.             c = conn.cursor()
  100.             sql="INSERT INTO [" + regs[0][i] + "](日期,資買進,資賣出,資現金償還,資前日餘額, \
  101.                                                 資今日餘額,資限額,券買進,券賣出,券現金償還, \
  102.                                                 券前日餘額,券今日餘額,券限額,資券互抵,註記) \
  103.                                         VALUES('" + date + "'," + regs[2][i] + "," + regs[3][i] + ", \
  104.                                                 " + regs[4][i] + ",  " + regs[5][i] + "," + regs[6][i] + ", \
  105.                                                 " + regs[7][i] + "," + regs[8][i] + ",  " + regs[9][i] + ", \
  106.                                                 " + regs[10][i] + "," + regs[11][i] + "," + regs[12][i] + ", \
  107.                                                 " + regs[13][i] + "," + regs[14][i]+ ",'" + regs[15][i] + "') ;"

  108.             c.execute(sql)
  109.         except Exception as e: #當日期不存在時,寫入資料到資料表中
  110.             pass
  111.         else:
  112.             c.close()
  113.             
  114.     conn.commit()
  115.     conn.close()

  116. # 以下為程式的啟始點:
  117. StartDate=input('請輸入開始擷取日期(西元日期如:2016/1/1):')
  118. EndDate=input('請輸入結束擷取日期(西元日期如:2016/1/31):')
  119. #處理日期還真的很麻煩
  120. ts=time.time()
  121. StartDate = time.strptime(StartDate, "%Y/%m/%d")
  122. EndDate =time.strptime(EndDate, "%Y/%m/%d")
  123. StartDate = datetime.date(StartDate[0], StartDate[1], StartDate[2])
  124. EndDate =  datetime.date(EndDate[0], EndDate[1], EndDate[2])
  125. RangeDate = datetime.timedelta(days = 1)
  126. while StartDate <= EndDate:
  127.     yy,mm,dd=str(StartDate).split('-')
  128.     dat=datetime.datetime(int(yy), int(mm), int(dd))
  129.     dd=dat.strftime('%Y/%m/%d')
  130.     year=str(int(dd[0:4])-1911)
  131.     date=dd.replace(dd[0:4], year)
  132.     print('目前執行網路擷取',date ,'日的資料,請稍後...')
  133.     re=read_network_data(date,1)
  134.     if re[0][0]=='查無資料':
  135.         print(date,'日,可能為休市日,查無資料。')
  136.         StartDate = StartDate + RangeDate
  137.         continue
  138.     print('檢查是否有新股票加入,請稍後...')
  139.     check_db_exists(regs=re)
  140.     print('將資料寫入資料庫中,請稍後...')
  141.     add_data(regs=re,date=dd)
  142.     StartDate = StartDate + RangeDate
  143.     te = time.time()
  144.     print('截至目前,時間已耗費:', int(te - ts),'秒')

  145. print('執行完畢!')
複製代碼

TOP

Untitled6.rar (4.96 KB)

TOP

回復 34# lpk187
我將 pandas 的處理稍加修改執行後,
產生錯誤訊息,是哪裡不對?
它一直說 OperationalError: near "0050": syntax error

TOP

回復 33# lpk187
將它存成 .db 以及 .sqlite 兩種不同 Extension Name,
結果如下: ( .sqlite  速度較快,檔案亦較小)

TOP

回復 33# lpk187

TOP

回復 37# c_c_lai


   這應該不會影響查詢吧!

TOP

回復 37# c_c_lai

c大是不是手動把資料記錄清除過,最前面那行不可逆的,像 l大說的  不影響查詢

TOP

回復 38# lpk187

TOP

        靜思自在 : 謊言像一朵盛開的鮮花,外表美麗,生命短暫。
返回列表 上一主題