Python实验1 |
您所在的位置:网站首页 › 诗字组合的名字 › Python实验1 |
Python实验1——网络爬虫及数据可视化
一、实验目标与基本要求实验目标基本要求
二、主要知识点、重点与难点主要知识点重点难点
三、实验过程设计获取网页获取数据保存到数据库数据预处理绘制独立数据图像绘制K线图数据转化、存储为Excel绘制股票信息分析图数据可视化主函数
运行结果遇到的问题实验的收获
一、实验目标与基本要求
实验目标
开发网络爬虫在东方财富、新浪财经或者纳斯达克等财经网站上爬取一只股票的每天的开盘价,收盘价,最高价,最低价等信息,并存储在数据库中,并开发GUI应用可视化。 基本要求(1) 掌握网络爬虫的开发方法; (2) 掌握Python开发数据库的GUI界面; (3) 掌握Matplotlib绘制股票的K线图; 二、主要知识点、重点与难点 主要知识点(1) 网络爬虫的基本知识; (2) 利用正则表达式对网页信息提取; (3) 数据库的访问和表中的数据操作; (4) Matplotlib库的使用。 重点(1) 网络爬虫框架的使用; (2) 正则表达式的使用; (3) 数据库存储数据。 难点(1) 利用正则表达式根据网页中的信息组织方式提取数据; (2) K线图的展现。 三、实验过程设计 获取网页a 获取原始数据 保存到数据库 数据预处理 绘制独立数据图像 绘制K线图 数据转化,存储为Excel 绘制股票信息分析图 数据可视化 获取网页 def getHtml(stack_code): data = requests.get("http://quotes.money.163.com/trade/lsjysj_" + stack_code + ".html#06f01", headers={"user-agent": "Mozilla/5.0"}) # 获得一个请求得到的静态网页 return data.text爬取的网站是网易财经的股票历史交易记录。经过观察发现,不同股票历史交易记录的区别在于中间的一段股票代码,于是通过输入股票代码来获取指定股票的交易网页。 为了便于下面的数据处理,直接返回网页的text,省去了一步处理过程。(json.dumps应该也可以获取内容,作用是把str数据直接转换成字典,但是对数据有格式要求) 获取数据json的函数dumps可以直接把网页转化成字典,但是可以自己实现的还是自己写。 def getData(data): month_data = [] soup = BeautifulSoup(data, "html.parser") # 爬取网页的工具 list = soup.find("div", class_="inner_box").find("table", class_="table_bg001 border_box limit_sale") # 看html,已经把不需要的都删了,数据在innerbox的table_bg001 border_box limit_sale下面 # print(list) dataList = list.find_all("tr")[1:] # 因为第一个tr后面是一堆th标签,不需要 # print(dataList) f = open("data.txt", "a+", encoding="utf-8") for item in dataList: kv = {} if isinstance(item, bs4.element.Tag): tdList = item.find_all("td") # print(tdList) kv["日期"] = tdList[0].text # 去掉td和/td,取中间的内容 kv["开盘价"] = tdList[1].text kv["最高价"] = tdList[2].text kv["最低价"] = tdList[3].text kv["收盘价"] = tdList[4].text kv["成交量"] = tdList[7].text month_data.append(kv) to_write = json.dumps(kv) f.write(to_write) f.close() return month_data首先通过BeautifulSoup得到网页格式处理的soup,通过浏览器访问防止反爬虫。 202120202019201820172016201520142013201220112010 ;; 四季度三季度二季度一季度 ;; 下载数据 日期 开盘价 最高价 最低价 收盘价 涨跌额 涨跌幅(%) 成交量(手) 成交金额(万元) 振幅(%) 换手率(%) 2021-05-14 6.94 8.10 6.78 8.10 1.35 20.00 489,575 36,666 19.56 15.30 2021-05-137.037.186.746.75-0.28-3.98291,38020,1606.269.112021-05-126.407.366.267.030.548.32429,97930,06916.9513.442021-05-116.536.586.256.49-0.15-2.26207,69613,3074.976.492021-05-106.587.066.486.64-0.12-1.78275,20918,4068.588.602021-05-077.107.156.566.76-0.25-3.57319,00521,6938.429.972021-05-066.737.356.607.010.416.21426,52929,50611.3613.332021-04-306.977.306.276.60-0.06-0.90529,43635,33315.4716.542021-04-295.506.665.416.661.1120.00382,60223,74122.5211.962021-04-285.645.865.535.55-0.27-4.64196,80411,0685.676.152021-04-276.066.145.655.82-0.44-7.03286,39216,7547.838.952021-04-266.286.485.896.26-0.39-5.86397,51224,3958.8712.422021-04-236.387.206.186.650.609.92593,69140,15916.8618.552021-04-225.036.055.036.051.0120.04349,40519,94920.2410.922021-04-215.155.155.035.04-0.08-1.5628,4851,4442.340.892021-04-205.175.245.125.12-0.07-1.3538,1351,9762.311.192021-04-195.155.255.125.190.030.5841,9402,1782.521.312021-04-164.975.194.955.160.193.8242,5362,1724.831.332021-04-155.045.054.944.97-0.10-1.9730,3431,5142.170.952021-04-144.915.084.875.070.183.6831,3851,5594.290.982021-04-135.045.054.824.89-0.11-2.2034,0501,6694.601.062021-04-125.095.124.985.00-0.12-2.3437,8991,9012.731.182021-04-095.155.245.115.120.050.9947,5922,4582.561.492021-04-085.295.295.075.07-0.18-3.4354,7692,8154.191.712021-04-075.215.285.195.250.040.7731,1961,6321.730.972021-04-065.195.265.135.210.040.7738,4932,0052.511.202021-04-025.065.185.065.170.040.7843,6752,2312.341.362021-04-015.305.345.055.13-0.13-2.4757,8462,9675.511.81通过查看网页源码,找到数据所在的标签是:名字为inner_box的div下的,名字为table_bg001 border_box limit_sale的table下的,每一个tr标签中的内容。这就可以通过soup的find方法找到数据了 list = soup.find("div", class_="inner_box"). find("table", class_="table_bg001 border_box limit_sale")list中存放的就是一堆tr标签,仍然保留html的格式。 dataList = list.find_all("tr")[1:]因为table下的第一项是一系列的th标签,没有数据,所以去掉这一项。 2021-05-14 6.94 8.10 6.78 8.10 1.35 20.00 489,575 36,666 19.56 15.30再看一下每一天数据的格式。 f = open("data.txt", "a+", encoding="utf-8") for item in dataList: kv = {} if isinstance(item, bs4.element.Tag): tdList = item.find_all("td") # print(tdList) kv["日期"] = tdList[0].text # 去掉td和/td,取中间的内容 kv["开盘价"] = tdList[1].text kv["最高价"] = tdList[2].text kv["最低价"] = tdList[3].text kv["收盘价"] = tdList[4].text kv["成交量"] = tdList[7].text month_data.append(kv) to_write = json.dumps(kv) f.write(to_write) f.close()把每一天的数据保存成一个字典,把一只股票的数据保存到一个列表中。tdlist存放了一天数据,通过下标找到对应的列数据,同时去掉标签tr,并保存到txt中。 保存到数据库 def Storage(data): my_database = mysql.connector.connect( host="localhost", user="root", passwd="123456", auth_plugin='mysql_native_password' ) cursor = my_database.cursor() sql_createDataBase = "create database if not exists stockData" cursor.execute(sql_createDataBase) sql_useDataBase = "USE stockData" cursor.execute(sql_useDataBase) sql_createTable = '''create table if not exists data( date DATE,/ opening_price float, closing_price float, highest float, lowest float) ''' cursor.execute(sql_createTable) for item in data: sql_Insert = '''Insert into data values ('{0}',{1},{2},{3},{4})'''.format(item['日期'], item['开盘价'], item['收盘价'], item['最高价'], item['最低价']) cursor.execute(sql_Insert) cursor.close() my_database.commit() my_database.close() print(my_database) 首先建立数据库连接,创建新的数据库和股票数据表,列名为爬取的数据内容。将之前的数据插入数据库,然后关闭数据库连接。注意在python中执行sql语句需要通过由标的execute函数执行,对于插入,运用了字符串的format函数,预留出每一个值,填入数组的对应位置。 因为画K线图函数需要用到元组形式的数据,这里做一个数据处理 def data_Pretreatment(month_data, date, opening_price, closing_price, highest, lowest): for data in month_data: my_date = data.get("日期") my_open = data.get("开盘价") my_close = data.get("收盘价") my_high = data.get("最高价") my_low = data.get("最低价") date.append(my_date) opening_price.append(my_open) closing_price.append(my_close) highest.append(my_high) lowest.append(my_low)遍历预处理之后的数据,整理成新的列表。 绘制独立数据图像 def draw(month_data,lowest): bar1 = Bar() bar1.add_xaxis(date) bar1.add_yaxis("最低价", lowest) bar1.set_series_opts( # 是否显示标签 label_opts=opts.LabelOpts(is_show=False) , markpoint_opts=opts.MarkPointOpts( data=[opts.MarkPointItem(type_="max", name="max"), opts.MarkPointItem(name="min", type_="min")] ), markline_opts=opts.MarkLineOpts(data=[opts.MarkLineItem(name="average", type_="average")])) bar1.set_global_opts( xaxis_opts=opts.AxisOpts( axislabel_opts=opts.LabelOpts(rotate=-60, font_size=10), ), yaxis_opts=opts.AxisOpts( name="价格:(元/股)", ), ) bar1.render("最低价.html") 这里用到了一个交互性的库pyecharts,可以把数据保存为静态html,而且可以与用户交互。注意到数据有三十个,一页是放不下的,因此设置数据的横坐标倾斜角度为60,保证能够在一页内显示所有数据。 通过处理之后的数据,很方便的作为画图函数的4个参数传入,这里同样有数据太多无法显示的问题,因为K线图细节很多,无法缩小,因此设置水平方向的滚动条,可以看到完整的数据图像。 这也是数据处理,一方面GUI可以显示Excel表格,另一方面下一张股票分析图需要DataFrame类型的股票数据,在这个函数里实现这两个功能。 def store_in_dataframe(month_data): my_list = [] for item in month_data: tmp = list(item.values()) my_list.append(tmp) # print(my_list) my_dataframe = pd.DataFrame(my_list, columns=["datetime", 'open', 'close', 'low', 'high', "trade_sum"]) print(my_dataframe) my_dataframe.to_excel("数据.xlsx") return my_dataframe 绘制股票信息分析图这是结合K线图对股票信息进行进一步分析,结合pyecharts,可以做到: 1.在一张图上显示多条曲线(Overlap的功能),用户可以自行选择隐藏不需要的曲线。 2.在K线图下方显示股票当天成交量的柱状图。 3.提示用户股票buy和sell的点供参考。 def back_testing_plot(table_name, indicator_name_list): # data preparation da = pd.DataFrame(data=table_name) # da['trade_sum'] = da['trade_sum'].apply(lambda vol: vol if vol > 0 else 0) date = da["datetime"].apply(lambda x: str(x)).tolist() k_plot_value = da.apply(lambda record: [record['open'], record['close'], record['low'], record['high']], axis=1).tolist() # K chart kline = Kline() kline.add("Back_testing Result", date, k_plot_value) indicator_lines = Line() for indicator_name in indicator_name_list: indicator_lines.add(indicator_name, date, da[indicator_name].tolist(), mark_point=["max", "min"], ) # trading volume bar chart bar = Bar() print(type(max(da["trade_sum"]))) bar.add("trade_sum", date, da["trade_sum"], tooltip_tragger="axis", is_legend_show=False, is_yaxis_show=False, yaxis_max=5 * max(da["trade_sum"]), ) # buy and sell v1 = date[10] v2 = da['high'].iloc[10] es = EffectScatter("buy") es.add("buy", [v1], [v2]) v1 = date[18] v2 = da['high'].iloc[18] es.add("sell", [v1], [v2], symbol="pin", ) overlap = Overlap() overlap.add(kline) overlap.add(indicator_lines, ) overlap.add(bar) overlap.add(es) overlap.render(path='高级图.html')细节: 向界面的panel添加两个按钮,同时指定on-click函数和update函数,将按钮和函数绑定,当监听到指定id的按钮被按下,就执行相应的更新函数,绘制新的K图和表格。 功能: 界面有一个输入框和两个按钮,用户可以直接在界面上看到股票的Excel数据,也可以通过保存在file目录下的静态网页查看之前绘制的任何一张图标。 当用户输入新的股票代号并点击更新时,首先会重新爬取股票数据,同时更新Excel表格中的数据和K线图、股票数据分析图中的数据。 主函数 def main(): htmlText = getHtml(str(600975)) month_data = getData(htmlText) month_data.sort(key=lambda k: k['日期']) month_data.sort(key=lambda x: pd.datetime.strptime("x['日期']", '%d/%m/%Y')) print(month_data) Storage(month_data) date = [] opening_price = [] closing_price = [] highest = [] lowest = [] draw(month_data, date, opening_price, closing_price, highest, lowest) app = App() my_list = [] for item in month_data: tmp = list(item.values()) my_list.append(tmp) app.data = my_list app.column_names = ["datetime", 'open', 'close', 'low', 'high', "trade_sum"] print(app.data) app.show() app.MainLoop() if __name__ == '__main__': main() 运行结果
没有能够把K线图嵌入到界面中,观察不够方便。 实验的收获1.学会了基本的html知识,懂得利用浏览器开发者工具获取需要的网络数据。 2.实践了在高级语言中进行sql语句的嵌入执行。 3.理解了Dataframe数据格式在库函数调用中的广泛运用,熟练掌握了数据预处理和格式转换。 4.面对数据无法全部显示的时候,能根据用户对数据的需求和数据的特性,修改数据的显示特征(压缩和滚动显示)。 5.实现前台界面和后台数据的交互,保证数据的实时更新。 |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |