美文网首页Python新世界
Flask框架小巧强悍?手把手教你打造港股通北水追踪器!不可商用

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

作者: 919b0c54458f | 来源:发表于2018-10-12 14:27 被阅读5次

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

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

进群:548377875   即可获取大量的学习教程以及PDF哦!

由数据可见,北水于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 ',

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)

相关文章

网友评论

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

    本文链接:https://www.haomeiwen.com/subject/inqgaftx.html