<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          價值十萬的代碼之二---手把手教你獲取數(shù)據(jù)篇

          共 9779字,需瀏覽 20分鐘

           ·

          2020-11-22 17:01

          文 |?閑歡

          來源:Python 技術(shù)「ID: pythonall」

          上篇文章 一份代碼幫我賺了10萬中,小醬承諾如果大家點贊數(shù)超過30個,我會繼續(xù)分享如何利用個股研報數(shù)據(jù)來進行分析。小醬是個信守承諾的小伙子,既然答應了大家,就一定會做到的。

          我們要利用個股研報數(shù)據(jù),肯定是會結(jié)合個股行情數(shù)據(jù)的,所以首先要獲取股票數(shù)據(jù),本篇我跟大家分享一下我是如何獲取個股行情數(shù)據(jù)的。

          選定目標

          現(xiàn)在獲取股票行情數(shù)據(jù)的渠道有好多,比較正規(guī)的途徑就是各種量化平臺的 API 接口,主要分兩類:

          1. 有條件免費或者可以在平臺上使用數(shù)據(jù)的量化平臺,例如聚寬(https://www.joinquant.com/)、Tushare平臺(http://tushare.org/)。
          2. 大型財經(jīng)平臺的量化平臺,例如同花順的 ?MindGO(http://quant.10jqka.com.cn/platform/html/home.html)、東方財富的 Choice 數(shù)據(jù)量化(http://quantapi.eastmoney.com/)。

          第一種渠道,如果你在他們平臺上去用 Python 寫交易策略模型進行回測很方便,平臺上是使用的 Jupyter Notebook 來編輯程序,但是如果想獲取行情數(shù)據(jù)到本地,自己自由支配就需要通過他們提供的 API 接口來獲取數(shù)據(jù),而 API 接口通常對數(shù)據(jù)量或者訪問頻次有限制,導致我們很難隨心所欲地獲取數(shù)據(jù)。

          第二種渠道,也可以在平臺上進行回測,想要獲取數(shù)據(jù)到本地基本上是需要交費成為會員才可以。

          為了圖免費方便,大多數(shù)人選擇第一種方式,在他們平臺上去寫各種策略模型或者程序?qū)崿F(xiàn)自己的邏輯,對模型進行回測。

          對于我個人來說,我選擇了第三種方式,不依靠免費平臺的數(shù)據(jù),也不花錢去購買數(shù)據(jù),而是靠個人能力獲取所有數(shù)據(jù)到本地存儲。因為我不喜歡依賴別人的平臺,萬一哪天突然垮掉了或者收費了呢?在有選擇的前提下,我更不愿意花費巨額資金去購買,雖然研究這個一方面也是為了賺錢,但是能省點是點,不是嗎?

          大家應該也猜到了我所謂的“個人能力”是啥,無非就是靠技術(shù)手段去獲取,雖然麻煩點,但是很香啊!

          我的主要目標網(wǎng)站就是國內(nèi)比較大的媒體網(wǎng)站的財經(jīng)版塊,有 搜狐財經(jīng)(https://q.stock.sohu.com/)、新浪財經(jīng)(http://vip.stock.finance.sina.com.cn/mkt/)、網(wǎng)易財經(jīng)(http://quotes.money.163.com/stock)和東方財富網(wǎng)。從這些財經(jīng)版塊的頁面去找到個股行情數(shù)據(jù),然后將其爬取到本地。

          這里面我自己長期固定的目標是網(wǎng)易財經(jīng),因為到目前為止,獲取數(shù)據(jù)比較穩(wěn)定,并且個股的信息比較豐富。下面我就分享一下我獲取個股每日行情數(shù)據(jù)的方法。

          分析目標頁面

          我們獲取數(shù)據(jù)的第一步是找到目標頁面,既然是獲取股票數(shù)據(jù),我們肯定是要找到網(wǎng)易財經(jīng)的股票頁面:http://quotes.money.163.com/stock。

          然后在這個頁面的左側(cè)導航欄中找到“漲跌排行”欄目,點擊選擇“滬深A股”,如下圖所示:

          網(wǎng)易財經(jīng)股票頁面

          我們就來到了最新的行情數(shù)據(jù)頁面,網(wǎng)址如下:

          http://quotes.money.163.com/old/#query=EQA&DataType=HS_RANK&sort=PERCENT&order=desc&count=24&page= 0

          如果當前時間是交易時間,那么這個頁面顯示的是實時行情,如果當前時間是非交易時間,那么這個頁面顯示的是最近交易日的收盤行情。我們來看看這個頁面:

          網(wǎng)易財經(jīng)滬深行情

          如果單純看這個網(wǎng)頁的網(wǎng)址,或許你會想是不是我替換一下 count 和 page 這兩個參數(shù)就可以獲取數(shù)據(jù)了。但是實際上替換 count 管用,可以改變頁面每頁的記錄數(shù),而 page 參數(shù),無論你填什么值,頁面都不會有變化。所以我們先放棄這個點,去看看頁面的請求,看能不能發(fā)現(xiàn)“天機”。

          逐條掃描請求,我們會發(fā)現(xiàn)有一個請求是這樣的:

          請求鏈接

          看起來這個返回結(jié)果是我們所需要的行情數(shù)據(jù)。找到它之后,接下來我們再來看看請求參數(shù):

          host:請求域名
          page:請求頁碼
          query:未知
          fields:獲取股票數(shù)據(jù)的列
          sort:股票數(shù)據(jù)排序方式
          order:排序順序
          count:每頁顯示數(shù)目
          type:請求類型

          對于我們來說,我們只需要關(guān)心 page、fields、count 這幾個參數(shù)就行,其他的就按照頁面的來,每次請求帶上一樣的值就好。而對于 fields 這個參數(shù),我覺得好不容易爬一次數(shù)據(jù),肯定數(shù)據(jù)列越全越好,所以全部都要吧,小孩才做選擇呢!我們點擊頁面下面的翻頁頁碼,可以觀察到 page 參數(shù)是變化的,因此我們可以根據(jù) page 的變化來獲取每一頁的數(shù)據(jù),從而獲取到所有股票行情數(shù)據(jù)。

          代碼實現(xiàn)

          第一步,肯定是發(fā)送請求,獲取返回數(shù)據(jù):


          def?get_data(self,?url):
          ????????response?=?requests.get(url,?headers=self.ua_header,?verify=False)
          ????????content?=?response.content.decode('unicode_escape')
          ????????return?content
          ????????

          接著,我會對請求到的數(shù)據(jù)做一些自定義的特殊處理,因為返回的數(shù)據(jù)信息當中可能會包含有“:”、“""”、“{}”之類的符號,從而影響到后續(xù)的數(shù)據(jù) json 解析,所以我必須想辦法先干掉他們:


          def?deal_json_invaild(self,?data):
          ????????data?=?data.replace("\n",?"\\n").replace("\r",?"\\r").replace("\n\r",?"\\n\\r")?\
          ????????????.replace("\r\n",?"\\r\\n")?\
          ????????????.replace("\t",?"\\t")
          ????????data?=?data.replace('":"',?'&&GSRGSR&&')\
          ????????????.replace('":',?"%%GSRGSR%%")?\
          ????????????.replace('","',?"$$GSRGSR$$")\
          ????????????.replace(',"',?"~~GSRGSR~~")?\
          ????????????.replace('{"',?"@@GSRGSR@@")?\
          ????????????.replace('"}',?"**GSRGSR**")
          ????????#?print(data)

          ????????data?=?data.replace('"',?r'\"')?\
          ????????????.replace('&&GSRGSR&&',?'":"')\
          ????????????.replace('%%GSRGSR%%',?'":')\
          ????????????.replace('$$GSRGSR$$',?'","')\
          ????????????.replace("~~GSRGSR~~",?',"')\
          ????????????.replace('@@GSRGSR@@',?'{"')\
          ????????????.replace('**GSRGSR**',?'"}')
          ????????#?print(data)
          ????????return?data

          注意,這里面是我平時跑程序時會經(jīng)常遇到的一些特殊字符的總結(jié)(血淋淋的教訓換來的),你以后可能會遇到其他的特殊字符,往這里面添加規(guī)則就行。

          再接下來,我們就要進入解析數(shù)據(jù)的環(huán)節(jié)了,解析比較簡單,直接轉(zhuǎn)換成 json 就行:


          def?parse_data(self,?data):
          ????????result_obj?=?json.loads(data)

          ????????obj?=?{}
          ????????obj['pagecount']?=?result_obj['pagecount']
          ????????obj['time']?=?result_obj['time']
          ????????obj['total']?=?result_obj['total']
          ????????list_str?=?result_obj['list']
          ????????stock_list?=?[]
          ????????if?list_str:
          ????????????data_list?=?list(list_str)
          ????????????for?s?in?data_list:
          ????????????????#?print(s)
          ????????????????stock?=?{}
          ????????????????stock['query_code']?=?s['CODE']
          ????????????????stock['code']?=?s['SYMBOL']
          ????????????????stock['name']?=?s['SNAME']
          ????????????????if?'PRICE'?in?s.keys():
          ????????????????????stock['close_price']?=?self.trans_float(s['PRICE'])
          ????????????????else:
          ????????????????????stock['close_price']?=?0.00
          ????????????????if?'HIGH'?in?s.keys():
          ????????????????????stock['top_price']?=?self.trans_float(s['HIGH'])
          ????????????????else:
          ????????????????????stock['top_price']?=?0.00
          ????????????????if?'LOW'?in?s.keys():
          ????????????????????stock['low_price']?=?self.trans_float(s['LOW'])
          ????????????????else:
          ????????????????????stock['low_price']?=?0.00
          ????????????????if?'OPEN'?in?s.keys():
          ????????????????????stock['open_price']?=?self.trans_float(s['OPEN'])
          ????????????????else:
          ????????????????????stock['open_price']?=?0.00
          ????????????????if?'YESTCLOSE'?in?s.keys():
          ????????????????????stock['last_price']?=?self.trans_float(s['YESTCLOSE'])
          ????????????????else:
          ????????????????????stock['last_price']?=?0.00
          ????????????????if?'UPDOWN'?in?s.keys():
          ????????????????????stock['add_point']?=?self.trans_float(s['UPDOWN'])
          ????????????????else:
          ????????????????????stock['add_point']?=?0.00
          ????????????????if?'PERCENT'?in?s.keys():
          ????????????????????stock['add_percent']?=?self.trans_float(s['PERCENT'])
          ????????????????else:
          ????????????????????stock['add_percent']?=?0.00
          ????????????????if?'HS'?in?s.keys():
          ????????????????????stock['exchange_rate']?=?self.trans_float(s['HS'])
          ????????????????else:
          ????????????????????stock['exchange_rate']?=?0.00
          ????????????????if?'VOLUME'?in?s.keys():
          ????????????????????stock['volumn']?=?self.trans_float(s['VOLUME'])
          ????????????????else:
          ????????????????????stock['volumn']?=?0.00
          ????????????????if?'TURNOVER'?in?s.keys():
          ????????????????????stock['turnover']?=?self.trans_float(s['TURNOVER'])
          ????????????????else:
          ????????????????????stock['turnover']?=?0.00
          ????????????????if?'TCAP'?in?s.keys():
          ????????????????????stock['market_value']?=?self.trans_float(s['TCAP'])
          ????????????????else:
          ????????????????????stock['market_value']?=?0.00
          ????????????????if?'MCAP'?in?s.keys():
          ????????????????????stock['flow_market_value']?=?self.trans_float(s['MCAP'])
          ????????????????else:
          ????????????????????stock['flow_market_value']?=?0.00
          ????????????????stock_list.append(stock)

          ????????obj['stock']?=?stock_list

          ????????return?obj

          至于這里面每一項的含義,大家可以參照頁面的列去一一對應。

          解析完數(shù)據(jù)后,我們就要將數(shù)據(jù)持久化,我這里選擇 mysql 存儲數(shù)據(jù),便于后續(xù)分析使用:


          def?insert_db(self,?obj_list,?day):
          ????????try:
          ????????????if?len(obj_list):
          ????????????????insert_attrs?=?['day',?'query_code',?'code',?'name',?'close_price',?'top_price',?'low_price',?'open_price',?'last_price',?'add_point',?'add_percent',?'exchange_rate',?'volumn',?'turnover',?'market_value',?'flow_market_value']
          ????????????????insert_tuple?=?[]
          ????????????????for?obj?in?obj_list:
          ????????????????????insert_tuple.append((day,
          ?????????????????????????????????????????obj['query_code'],
          ?????????????????????????????????????????obj['code'],
          ?????????????????????????????????????????obj['name'],
          ?????????????????????????????????????????obj['close_price'],
          ?????????????????????????????????????????obj['top_price'],
          ?????????????????????????????????????????obj['low_price'],
          ?????????????????????????????????????????obj['open_price'],
          ?????????????????????????????????????????obj['last_price'],
          ?????????????????????????????????????????obj['add_point'],
          ?????????????????????????????????????????obj['add_percent'],
          ?????????????????????????????????????????obj['exchange_rate'],
          ?????????????????????????????????????????obj['volumn'],
          ?????????????????????????????????????????obj['turnover'],
          ?????????????????????????????????????????obj['market_value'],
          ?????????????????????????????????????????obj['flow_market_value']))
          ????????????????values_sql?=?['%s'?for?v?in?insert_attrs]
          ????????????????attrs_sql?=?'('+','.join(insert_attrs)+')'
          ????????????????values_sql?=?'?values('+','.join(values_sql)+')'
          ????????????????sql?=?'insert?into?%s'?%?'stock_info'
          ????????????????sql?=?sql?+?attrs_sql?+?values_sql
          ????????????????try:
          ????????????????????print(sql)
          ????????????????????for?i?in?range(0,?len(insert_tuple),?20000):
          ????????????????????????self.cur.executemany(sql,?tuple(insert_tuple[i:i+20000]))
          ????????????????????????self.conn.commit()
          ????????????????except?pymysql.Error?as?e:
          ????????????????????self.conn.rollback()
          ????????????????????error?=?'insertMany?executemany?failed!?ERROR?(%s):?%s'?%?(e.args[0],?e.args[1])
          ????????????????????print(error)
          ????????except?Exception:
          ????????????#輸出異常信息
          ????????????traceback.print_exc()

          送佛送到西,順便附上建表語句吧:


          CREATE?TABLE?`stock_info`?(
          ??`id`?int(11)?unsigned?NOT?NULL?AUTO_INCREMENT,
          ??`day`?varchar(64)?NOT?NULL?DEFAULT?''?COMMENT?'日期',
          ??`query_code`?varchar(20)?DEFAULT?'',
          ??`code`?varchar(10)?DEFAULT?NULL?COMMENT?'股票代碼',
          ??`name`?varchar(64)?DEFAULT?NULL?COMMENT?'名稱',
          ??`close_price`?double?DEFAULT?NULL?COMMENT?'收盤價',
          ??`top_price`?double?DEFAULT?NULL?COMMENT?'最高價',
          ??`low_price`?double?DEFAULT?NULL?COMMENT?'最低價',
          ??`open_price`?double?DEFAULT?NULL?COMMENT?'開盤價',
          ??`last_price`?double?DEFAULT?NULL?COMMENT?'前收盤價',
          ??`add_point`?double?DEFAULT?NULL?COMMENT?'漲跌額',
          ??`add_percent`?double?DEFAULT?NULL?COMMENT?'漲跌幅',
          ??`exchange_rate`?double?DEFAULT?NULL?COMMENT?'換手率',
          ??`volumn`?double?DEFAULT?NULL?COMMENT?'成交量',
          ??`turnover`?double?DEFAULT?NULL?COMMENT?'成交金額',
          ??`amplitude`?double?DEFAULT?NULL?COMMENT?'振幅',
          ??`market_value`?double?DEFAULT?NULL?COMMENT?'總市值',
          ??`flow_market_value`?double?DEFAULT?NULL?COMMENT?'流通市值',
          ??`flag`?int(11)?NOT?NULL?DEFAULT?'0',
          ??PRIMARY?KEY?(`id`),
          ??KEY?`day`?(`day`,`query_code`),
          ??KEY?`code_name`?(`code`,`name`)
          )?ENGINE=InnoDB?AUTO_INCREMENT=3953?DEFAULT?CHARSET=utf8;

          運行程序,你就能在數(shù)據(jù)庫中看到行情數(shù)據(jù)了。如果不想每天手動運行的話,可以寫個定時,每天在收盤后自動運行,當然丟服務(wù)器上更好了。這樣每天獲取當天最新的行情數(shù)據(jù),日積月累,你就可以獲取到從今以后的股票行情數(shù)據(jù)了。

          總結(jié)

          本文以網(wǎng)易財經(jīng)為例,手把手分享怎樣獲取股票行情數(shù)據(jù),希望對大家有幫助。但是大家記住一點,獲取數(shù)據(jù)只是自己分析研究使用,千萬不要違反我們的職業(yè)道德哦。

          看到這里,大家可能會想:這只是獲取一天的行情數(shù)據(jù),并沒有歷史數(shù)據(jù),如果我今天要使用歷史數(shù)據(jù)分析,那不是撲街啦?

          這個想法是對的,大家不要著急,本文的數(shù)據(jù)只是后續(xù)步驟的前提,先給我點個在看,我會繼續(xù)分享如何獲取所有股票的歷史行情數(shù)據(jù)。

          PS公號內(nèi)回復「Python」即可進入Python 新手學習交流群,一起 100 天計劃!


          老規(guī)矩,兄弟們還記得么,右下角的 “在看” 點一下,如果感覺文章內(nèi)容不錯的話,記得分享朋友圈讓更多的人知道!

          代碼獲取方式

          識別文末二維碼,回復:201121

          瀏覽 61
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  超碰在线97啪啪啪 | 成人理伦A级A片在线论坛 | 国产一级不卡在线 | 天天大逼视频 | 操逼逼综合网 |