python自学-class20-爬取东方财富网股票数据(爬虫)

前俩天学习了正则表达式以及爬虫基础应用,于是我再结合先前一些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,并且保存路径需要加转义字符(太菜了这都不能在代码里解决),下图可以看出成功创建文件夹并且保存,
在这里插入图片描述
让我看看同时下载多个看看:在这里插入图片描述
小结:
搞定一看时间差不多到饭点,干饭人,干饭魂,干饭都是人上人!!!!
实际还有很多可以值得改善的地方,比如可以加入分析,制图(折线图,直方图),这些都很值得学习,下次有空一点要完善分析制图的功能;还有本来想抓取一个实时的数据显示,但是发现在交易时间内并不能简单抓取各个数据,交易时间内是显示"-"的不显示数据,只有收盘后才会显示数据,暂时还想不到解决方法,知识储备不足;
这个爬取数据做的还是很粗糙,还需要更加努力学习,越努力,越幸运;

猜你喜欢

转载自blog.csdn.net/weixin_46837674/article/details/113563740