python自学
前俩天学习了正则表达式以及爬虫基础应用,于是我再结合先前一些UI界面设计的知识做一个股票数据查询的小工具,不过还不具备数据分析的功能;
刚开始使用了一些博主提供的网址(“http://quote.eastmoney.com/stocklist.html”)去抓取股票列表
import re
import urllib
import urllib.request
def getpage(path):
data=urllib.request.urlopen(path).read().decode('utf-8')
return data
#find没有括号抓取全部,有括号抓取括号内,内容有括号转义字符\( \)
def getcode(data):
regex_str="<li><a href=\"list,([6|9]\d{5}).html\">"
#regex_str="<li><a href=\"list,hk([0-9]\d{4}).html\">\D\d{5}\D(.*?)<"
pat=re.compile(regex_str) #预编译
codelist=pat.findall(data)
return codelist
path="http://quote.eastmoney.com/stocklist.html"
data=getpage(path) #抓取网页源代码
print(data) #打印网页全部信息
codelist=getcode(data)
但是抓不出来,改了半天正则表达式,没有效果,然后我打印了网页源代码,苦苦寻找,然后在网页源代码中并没有找到有关具体股票的编号与名称信息(WTF??),奇怪的是,我在网页用开发者工具是可以找到相关信息的,也就是说抓取网页源代码时没有把这部分信息抓取下来(害!)这个问题就超出我的能力了;
于是我另辟蹊径,在网页股票社区个股吧(http://guba.eastmoney.com/remenba.aspx?type=1&tab=1)找到了股票列表
接下来只需要在开发者工具中看好源代码的格式,写好正则表达式即可
我提取股票代码与名称用到的正则表达式:
regex_str = "<li><a href=\"list,([0-9]\d{5}).html\">\D\d{6}\D(.*?)<"
然后发现提取港股时发生错乱了,淦!命运多舛!然后又去查看港股的源代码,然后看到:哦,港股代码只有5位,前面还加了hk,好呗,那我就再写一个做好区分:
regex_str = "<li><a href=\"list,hk([0-9]\d{4}).html\">\D\d{5}\D(.*?)<"
于是大功告成,我写的搜索函数(SearchStock)如下:
import urllib
import urllib.request
import re
class Search:
def __init__(self,slect):
self.choice=slect
def SearchAll(self):
path = "http://guba.eastmoney.com/remenba.aspx?type=1&tab=" + self.choice
if self.choice == '3': #港股规则不同需要重新判断
regex_str = "<li><a href=\"list,hk([0-9]\d{4}).html\">\D\d{5}\D(.*?)<"
else:
regex_str = "<li><a href=\"list,([0-9]\d{5}).html\">\D\d{6}\D(.*?)<"
data = self.getpage(path)
codelist = self.getcode(data, regex_str)
if self.choice != '3': #港股
codelist[0:] = codelist[30:]
return codelist
def getpage(self,path):
data = urllib.request.urlopen(path).read().decode('utf-8')
return data
def getcode(self,data, regex_str):
pat = re.compile(regex_str) # 预编译
codelist = pat.findall(data)
return codelist
股票列表做完了,好像有点简单,那就再弄一个股票数据下载,将历年数据爬下来保存。在网上搜索,发现163一个神奇的网址,可以download东方财富历年数据(WOW!!!)
#http://quotes.money.163.com/service/chddata.html?code=1300133&end=20210201&fields=TCLOSE;HIGH;LOW;TOPEN;CHG;PCHG;TURNOVER;VOTURNOVER;VATURNOVER;TCAP;MCAP
#code=1300133&end=20210201 1代表深市(0代表沪市) 300133代表股票代码 20210201代表截至日期
说干就干,下载股票用到了urlretrieve(url,path),保存为.csv文件:
import urllib.request
import urllib
url="http://quotes.money.163.com/service/chddata.html?code=1300133&end=20210201&fields=TCLOSE;HIGH;LOW;TOPEN;CHG;PCHG;TURNOVER;VOTURNOVER;VATURNOVER;TCAP;MCAP"
path="D:\\Python代码\\class20\\down\\300133.csv"
urllib.request.urlretrieve(url,path) #根据url下载到路径下
好,基础功能解决了,那么如果下载路径是自定义的呢,怎么判断自定义的路径下有么有相同的文件夹,以及若没有怎么创建一个呢,这时候就用到了面向百度编程,我找到了os的一个函数:
if not os.path.exists(path):
os.makedirs(path) #指定路径创建文件夹
既然保存路径可以自定义,那么想要查找的股票也应该可以自定义,于是将上面神奇的下载地址改为:
url = "http://quotes.money.163.com/service/chddata.html?code="+"0"+code[0]+"&end="+data+"&fields=TCLOSE;HIGH;LOW;TOPEN;CHG;PCHG;TURNOVER;VOTURNOVER;VATURNOVER;TCAP;MCAP"
再完善一下我的下载函数就出来了(DownloadStock):
import urllib
import urllib.request
import os
class Down:
def __init__(self,code,data,path):
self.code=code
self.data=data
self.path=path
def downloadstock(self):
# 判断文件夹是否存在
self.path = self.path + "\\" + self.data
if not os.path.exists(self.path):
os.makedirs(self.path) # 指定路径创建文件夹
url = "http://quotes.money.163.com/service/chddata.html?code=" + self.code + "&end=" + self.data + "&fields=TCLOSE;HIGH;LOW;TOPEN;CHG;PCHG;TURNOVER;VOTURNOVER;VATURNOVER;TCAP;MCAP"
datapath = self.path + "//" + self.code + ".csv"
urllib.request.urlretrieve(url, datapath) # 根据url下载到路径下
看了看时间,嗯,今天学习时间还多着呢,还没到玩耍的时间,好,那我就再给他加上之前学习的UI界面,顺便稍微使用了继承的方法来初始化界面,简化代码,于是界面输入函数(inputview),继承基类函数(BaseWindowShow),列表显示函数(ListShow)相继出炉:
界面输入函数(inputview):
#coding=gbk
import tkinter
from tkinter import ttk
import 爬取东方财富股票数据.SearchStock
import 爬取东方财富股票数据.DownloadStock
import 爬取东方财富股票数据.BaseWindowShow
import 爬取东方财富股票数据.ListShow
class InputView(爬取东方财富股票数据.BaseWindowShow.BaseWindowShow):
def __init__(self):
爬取东方财富股票数据.BaseWindowShow.BaseWindowShow.__init__(self)
self.entry1 = tkinter.Entry(self.win) #导入文本框,输入股票代码
self.entry1.place(x=250,y=0)
self.entry2 = tkinter.Entry(self.win) #导入文本框,输入截至时间
self.entry2.place(x=400,y=0)
self.entry3 = tkinter.Entry(self.win) #导入文本框,输入保存路径
self.entry3.place(x=550,y=0)
self.comdvalue = tkinter.StringVar() # 窗体自带文本,新建一个值
self.comboxdc = ttk.Combobox(self.win, textvariable=self.comdvalue,width=30) # 初始化
self.comboxdc["values"] = ("单个股票数据下载","下载多个","全部下载")
self.comboxdc.current(0) # 选择第一个
self.comboxdc.bind("<<ComboboxSelected>>", self.go) # 绑定事件与函数
self.comboxdc.place(x=0,y=0)
self.button2 = tkinter.Button(self.win,text = "下载",command = self.download) #导入搜索键,command表示绑定search的行为
self.button2.place(x=750,y=0)
self.button1 = tkinter.Button(self.win,text = "股票一览表",command = self.search) #导入搜索键,command表示绑定search的行为
self.button1.place(x=300,y=50)
self.comvalue = tkinter.StringVar() # 窗体自带文本,新建一个值
self.comboxlist = ttk.Combobox(self.win, textvariable=self.comvalue,width=30) # 初始化
self.comboxlist["values"] = ("沪市", "深市", "港股")
self.comboxlist.current(0) # 选择第一个
self.comboxlist.bind("<<ComboboxSelected>>", self.go) # 绑定事件与函数
self.comboxlist.place(x=0,y=50)
self.select="1"
def go(self,*args):
if(self.comboxlist.get()=='沪市'): #保存选中的值
self.select='1'
elif(self.comboxlist.get()=='深市'):
self.select='2'
elif(self.comboxlist.get()=='港股'):
self.select='3'
def search(self):
data=爬取东方财富股票数据.SearchStock.Search(self.select)
stockdata=data.SearchAll()
inserstr=爬取东方财富股票数据.ListShow.Listshowdata()
if(self.comboxlist.get()=='沪市'): #在股票网址中 sh表示沪市,sz表示深市,hk表示港股
inser="sh"
elif(self.comboxlist.get()=='深市'):
inser="sz"
elif(self.comboxlist.get()=='港股'):
inser="hk"
for data in stockdata:
#按照规则拼接出股票网址
inserstr.addata(inser+data[0]+'-'+data[1]+"网址:"+"http://quote.eastmoney.com/"+inser+data[0]+".html?code="+data[0])
def download(self):
if (self.comboxdc.get()=="单个股票数据下载"):
#code 股票代码 data截至时间 path保存路径
#这三个的赋值必须每次都重新赋值,不能放到if语句前简化代码
code=self.entry1.get()
print(type(code))
data = self.entry2.get()
path = self.entry3.get()
data = 爬取东方财富股票数据.DownloadStock.Down(code, data, path)
data.downloadstock()
elif(self.comboxdc.get()=="下载多个"):
codelist=self.entry1.get().split(" ")
print(codelist)
for code in codelist:
print(type(code))
data = self.entry2.get()
path = self.entry3.get()
data = 爬取东方财富股票数据.DownloadStock.Down(code, data, path)
data.downloadstock()
elif(self.comboxdc.get()=="全部下载"):
data = 爬取东方财富股票数据.SearchStock.Search(self.select)
stockdata = data.SearchAll()
for datas in stockdata:
code=datas[0]
data = self.entry2.get()
path = self.entry3.get()
data = 爬取东方财富股票数据.DownloadStock.Down(code, data, path)
data.downloadstock()
继承基类函数(BaseWindowShow):
import tkinter
class BaseWindowShow:
def __init__(self):
self.win=tkinter.Tk() #构造窗体
self.win.geometry("800x800+300+0") #搜索数据显示窗口
def show(self):
self.win.mainloop()
列表显示函数(ListShow):
import 爬取东方财富股票数据.BaseWindowShow
import tkinter
class Listshowdata(爬取东方财富股票数据.BaseWindowShow.BaseWindowShow):
def __init__(self):
爬取东方财富股票数据.BaseWindowShow.BaseWindowShow.__init__(self)
self.list=tkinter.Listbox(self.win,width=200) #文本编辑器
self.list.pack()
def addata(self,inserstr):
self.list.insert(tkinter.END,inserstr)
最后顺便写个主函数(Main)吧:
import 爬取东方财富股票数据.inputview
start=爬取东方财富股票数据.inputview.InputView()
start.show()
Python Package:
然后看看效果:
因为懒得加判断,所以输入股票代码时深市要加0,沪市要加1,并且保存路径需要加转义字符(太菜了这都不能在代码里解决),下图可以看出成功创建文件夹并且保存,
让我看看同时下载多个看看:
小结:
搞定一看时间差不多到饭点,干饭人,干饭魂,干饭都是人上人!!!!
实际还有很多可以值得改善的地方,比如可以加入分析,制图(折线图,直方图),这些都很值得学习,下次有空一点要完善分析制图的功能;还有本来想抓取一个实时的数据显示,但是发现在交易时间内并不能简单抓取各个数据,交易时间内是显示"-"的不显示数据,只有收盘后才会显示数据,暂时还想不到解决方法,知识储备不足;
这个爬取数据做的还是很粗糙,还需要更加努力学习,越努力,越幸运;