加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

Flask框架小巧强悍?手把手教你打造港股通北水追踪器!不可商用

发布时间:2020-12-17 00:54:59 所属栏目:Python 来源:网络整理
导读:1.该文章整理自台湾新闻,可能与实际情况有出入,请领会其文章精髓。(滑稽) 2.若手机看代码出现折行,建议点击阅读原文查看。(懒死我得了) 欢迎进群:548377875 ? 里面已经有很多小伙伴上传了大量的学习资料!以及学习交流的好地方! 由数据可见,北水于

1.该文章整理自台湾新闻,可能与实际情况有出入,请领会其文章精髓。(滑稽)

2.若手机看代码出现折行,建议点击阅读原文查看。(懒死我得了)

欢迎进群:548377875 ? 里面已经有很多小伙伴上传了大量的学习资料!以及学习交流的好地方!

由数据可见,北水于5月头便开始减持腾讯(0700),直到8月底才沽压稍敛。至于汇丰(0005),则自年头一轮追入后,近期才再见北水捧场,但声势远不及年头强大。一些北水持重货的股份,如新华制药(0719),虽然股价受政策影响大幅回落,但北水仍然密密吸纳,未有泄气情况。种种走势,用以下的程式便可一目了然。

读取数据的程式,主要用了我过去常用的Selenium及BeautifulSoup框架,模拟人手逐页下载数据,并将其组合成一个资料库供之后使用。相比人手逐页copy & paste,程式可以三数分钟便下载过百日的数据,而且做了基本整理,正是自动化的好处。不过,实际处理上来,仍有一些复杂的地方,如公司改名,便会出现一个股票编号、两个公司名称的情况,又如公司供股,也有可能会出现临时股票编号,而原来的股票编号所撷取的数据便出现断层。现时程式只处理首一个情况,未能处理第二个情况(笔者太懒),惟相信后者占整体数据只是少数,有兴趣的读者不妨完善之。程式northwater.py已放于文末,只是短短数十行程式。

笔者利用这程式,下载了今年至今的所有股份持股量数据,之后便要用flask来撰写一个可让网页读到及让用户互动的程式。这方面准备工夫较多,先下载flask框架,再设定一个python的虚拟环境(virtual environment),然后把程式需要用到的框架都写到一个requirements.txt的文字档案内,这是方便之后云端服务了解程式的需要,不用每次均下载一大堆无用的框架,浪费资源。这些设定都是三几行指令码的事情,读者可到flask的官方网页了解。

前期准备功夫完成后,便可以撰写程式,输入flask框架及相关数据库,其主要程序结构如下:

 1app = Flask(__name__)
 2
 3@app.route("/",methods=['POST','GET'])
 4
 5def submit_new_profile():
 6
 7 if request.method == 'POST':
 8
 9 .
10
11 .
12
13 return render_template(...)
14
15 elif request.method == 'GET':
16
17 。
18
19 。
20
21 return render_template(...)

首行是指定动作,第二行则是当在首页出现存取表格资料时启动submit_new_profile程序,若是用户输入资料,则request.method是'POST',按照用户输入的股票编号抽取数据库中的时序数据,然后再制作相关的图形,并更新index.html档案。

除了以上几行程式外,其余与Python一般的程式无异,详细程式看文末的main.py列表。

各样元素齐备后,便可以在flask模拟的一个简单本地伺服器上测试,确定程式无误,便可以选择一个云端服务商把程式上线(google cloud,亚马逊的AWS,或微软的Azure均可),笔者则选择免费的Pythonanywhere ,先登记一个帐户,然后开设一个新的web app,再把程式上载,包括requirements.txt,main.py,index.html(这档案一般会放在templates的子目录下) ,以及相关的数据库、图片及字型库。大功告成?

别想得太美了,整个过程,最令人沮丧的,并非要学习试用flask框架,而是除虫工作,以为在本地伺服器环境下运作正常的,到云端就不知为何无法再运作了,看错误讯息永远摸不着头脑,左查右查之下,才发现Pythonanywhere要求载入档案必须输入完整的档案路径,否则会发出档案不存在的警告。

另一个痛点,是广受欢迎的绘图框架matplotlib并不支援中文,若要显示中文,必须指定一个中文字库,方能正常显示。具体作法坊间有很多,但不是招招都管用,这又成为一个实验试错的过程,笔者现时用的是google开发的思源宋体。

虽然今次颇多挑战,但因为flask可以将完成品直接送到网民面前,让不懂Python的人也能直接使用,而且日后还会多多使用,倒也不算白费功夫。事实上,用flask来撰写web app,令Python应用可以直接与互联网语言html配搭,加上云端服务,便可以直接执行,连伺服器设定等繁琐工作都可以悭返。昔日写web application可能要学php,mysql等后台语言,但现在都可以由Python一手包办,这正是Python的强大之处。

 1来自 bs4 进口 BeautifulSoup
 2将 pandas 导入为 pd
 3导入请求
 4进口重新
 5进口时间
 6导入日期时间
 7来自 selenium import webdriver
 8来自 selenium.webdriver.support.ui 导入 WebDriverWait
 9从 selenium.webdriver.support 导入 expected_conditions 作为 EC
10从 selenium.webdriver.common.by 进口通过
11
12尝试:
13 table = pd.read_csv(' northwater.csv ')
14除了 IOError:
15 table = pd.DataFrame( columns = [ '股票编号','公司名称' ])
16 table.to_csv(' northwater.csv ',index = False)
17
18targetpage = “ http://www.hkexnews.hk/sdw/search/mutualmarket_c.aspx?t=hk ”
19
20def gendate(start_date,end_date):
21 dates = [start_date + datetime.timedelta(n)for n in range(int((end_date - start_date).days)+ 1)]
22 date_string = []
23 对于我在 范围(LEN(日期)):
24 temp = f ' { dates [i]:% Y % m % d } '
25 date_string.append(TEMP)
26 return date_string
27
28#检查日期是否已加载
29def checknewdate(date,alldate):
30 如果日期在 alldate:
31 返回 False
32 否则:
33 返回 True
34
35def loadpage(目标页面,日期):
36 年=日期[:4 ]
37 月=日期[ 4:6 ]
38 day = date [ 6:]
39
40 driver.get(targetpage)
41 在 driver.title中断言“ HKEX ” 
42
43 driver.find_element_by_xpath(“ // select [@ name ='ddlShareholdingDay'] / option [text()=' ” + day + “ '] ”)。click()
44 driver.find_element_by_xpath(“ // select [@ name ='ddlShareholdingMonth'] / option [text()=' ” + month + “ '] ”)。click()
45 driver.find_element_by_xpath(“ // select [@ name ='ddlShareholdingYear'] / option [text()=' ” + year + “ '] ”)。click()
46 driver.find_element_by_name(“ btnSearch ”)。click()
47
48 断言 “没有找到结果。” 不是 在 driver.page_source
49
50 time.sleep(2)
51 page = driver.page_source
52
53 返回页面
54
55 def readpage(页面,日期):
56 汤= BeautifulSoup(页面,' html.parser ')
57 record = soup.find_all(' tr ',class_ = re.compile(r “ ^ row ”))
58
59 code_tags = [] 
60 name_tags = [] 
61 nostock_tags = [] 
62
63 for in in range(len(record)):
64 code_tags.append(int(record [i] .select(' td ')[ 0 ] .get_text()。strip()))
65 name_tags.append(record [i] .select(' td ')[ 1 ] .get_text()。strip())
66 nostock_tags.append(int(record [i] .select(' td ')[ 2 ] .get_text()。strip()。replace(',',' ')))
67
68 table = pd.DataFrame({
69 "股票编号" : code_tags,70 "公司名称" : name_tags,71 日期:nostock_tags,
72 })
73
74 返回表
75
76def appenddata(table,temptable):
77 result = pd.merge(table,temptable,on = [ '股票编号','公司名称' ],how = ' outer ' )
78 返回结果
79
80START_DATE = datetime.date(2018,9,1)
81END_DATE = datetime.date(2018,9,29)
82dates = gendate(start_date,end_date)
83
84driver = webdriver.Firefox()
85
86对于我在 范围(LEN(日期)):
87 如果 checknewdate(dates [i],alldate):
88 page = loadpage(targetpage,dates [i])
89 temptable = readpage(页面,日期[i])
90 table = appenddata(table,temptable)
91 alldate = list(table)[ 2:]
92
93driver.close() 
94
95table.to_csv(' northwater.csv ',index = False)
 1#!/ usr / bin / env python
 2来自 flask 导入 Flask,render_template,flash,request,jsonify,Markup
 3导入 matplotlib
 4matplotlib.use(' Agg ')
 5将 matplotlib.pyplot 导入为 plt
 6将 matplotlib.font_manager 导入为 mfm
 7将 matplotlib.ticker 导入为自动收报机
 8将 pandas 导入为 pd
 9import io,base64
10
11font_path = “/ home / bigfish / mysys / NotoSerifCJKtc-Regular.otf ”
12prop = mfm.FontProperties(fname = font_path,size = 30)
13table = pd.read_csv('/ home / bigfish/mysite/northwater.csv ')
14
15app = Flask(__name__)
16
17def sortdate(表):
18 alldate = list(table)[ 2:]
19 alldate.sort()
20 cols = list(table)[ 0:2 ] + alldate
21 table = table [cols]
22 返回表
23
24result = sortdate(table)
25
26def checkcodeduplicate(代码):
27 tseries = result[result[ '股票编号' ] == code]
28 print(len(tseries))
29 如果 len(tseries)> 1:
30 t1 = tseries.iloc [ 0 ]
31 t2 = tseries.iloc [ 1 ]
32 tseries.iloc [ 0 ] = t1.combine_first(t2)
33 tseries = tseries [:1 ]
34 返回 tseries
35
36
37@ app.route(“ / ”,methods = [ ' POST ',' GET ' ])
38def submit_new_profile():
39 代码= 700
40 name = “ ”
41 submit_value = “ ”
42 tseries_table = “ ”
43
44 如果 request.method == ' POST ':
45 code = int(request.form [ ' selected_code ' ])
46 submit_value = request.form [ ' submit ' ]
47
48 尝试:
49 tseries = checkcodeduplicate(代码)
50 name = tseries[ '公司名称' ].iat[ 0 ]
51 tseries = tseries.iloc [:,2:]
52 tseries = tseries.T
53 tseries.columns = [code]
54 tseries.index.name = '日期'
55 change = tseries.diff()
56 pattern = ' { :,。0f } '。 format
57
58 plt.rcParams [ “ figure.figsize ” ] =(10,10)
59 fig = plt.figure()
60 斧= fig.add_subplot(2,1,1)
61 ax.xaxis.set_major_locator(ticker.MultipleLocator(40))
62 ax.plot(T系列)
63 plt.title(name,fontproperties = prop)
64 AX2 = fig.add_subplot(2,1,2)
65 ax2.plot(其他城市)
66 ax2.xaxis.set_major_locator(ticker.MultipleLocator(40))
67 plt.axhline(linewidth = 1,color = ' r ')
68
69 img = io.BytesIO()
70 plt.savefig(img,format = ' png ')
71 img.seek(0)
72 plot_url = base64.b64encode(img.getvalue())。decode()
73
74 return render_template(' index.html ',
75 model_plot = Markup('  '。 format(plot_url)),
76 selected_code = str(代码),
77 name = name,
78 tseries_table =标记(tseries.to_html()))
79
80 除了:
81 return render_template(' index.html ',
82 model_plot = “ ”,
83 selected_code = str (code),name = "你选择的股票没有数据",84 tseries_table = “ ”)
85
86
87 elif request.method == ' GET ':
88 return render_template(' index.html ',
89 model_plot = ' ',
90 selected_code = str(代码),
91 name = name,
92 tseries_table = “ ”)
93
94#在本地运行app时
95如果 __name__ == ' __main__ ':
96 app.run(debug = False)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读