美文网首页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