股票数据导出excel(股票数据爬取)
本文通过具体的案例,让读者掌握Python在爬虫项目中的应用。通过本文的学习,读者可以掌握分析网页的技巧、Python编写网络程序的方法、Excel的操作,以及正则表达式的使用。这些都是爬虫项目中必备的知识和技能。
实例描述:通过编写爬虫,将指定日期时段内的全部上市公司股票数据爬取下来,并按照股票代码保存到相应的Excel文件中。
本文共计2100字左右。目录结构如下。
1 爬取股票代码
1.1 找到目标网站
1.2 打开调试窗口,查看网页代码
1.3 在网页源码中找到目标元素
1.4 分析目标源代码,找出规律
1.5 编写代码抓取股票代码
1.6 运行代码,显示结果
2 爬取股票内容
2.1 编写代码抓取批量内容
2.2 运行代码显示结果
本案例主要分为两大步骤:
(1)要知道上市公司有哪些;
(2)根据每一个上市公司的股票编号爬取数据。
由于两部分代码相对比较独立,可以做成两个代码文件。一个文件用来爬取股票代码,另一个文件用来爬取股票内容。
1 爬取股票代码爬取股票代码的基本思路是:
(1)分析网站上的网页源代码,找到目标代码。
(2)利用正则表达式,在整个网页里搜索目标代码,从而提取出所要的信息(股票代码)。
有关金融证券领域的网站一般都会有上市公司的股票代码信息。随便找一个即可。
1.1 找到目标网站
使用Chrome浏览器访问链接:
http://quote.eastmoney.com/stocklist.html。可以看到全部的股票代码。
股票代码网页
1.2 打开调试窗口,查看网页代码
保持当前浏览器窗口为活动页面,按F12键显示出网页的源代码调试窗口,单击调试窗口的Element按钮,可以看到页面的HTML代码。
调试窗口
1.3 在网页源码中找到目标元素
网页的源代码是按照HTML的语法规则自动折叠的。可以用光标在HTML代码中任意单击将其展开。当光标移动到某个元素时,会看到右测网页中对应的元素会有变化,呈现被选中状态。
选中元素
上图中,箭头所指的网页源代码,就是需要关注并爬取的内容。
1.4 分析目标源代码,找出规律
分析上图中左侧显示的内容,与右侧代码之间的对应关系。不难发现,左侧显示的每个股票代码所对应的源代码格式都是固定的。
目标源代码内容
这条源代码内容,便是要找到的目标代码。将其整理成如下字符串模版:
<li><a target="_blank" href="
http://quote.eastmoney.com/股票代码.html
其中,“.html”前面的“股票代码”就是需要抓取的内容。分析到这里,开发任务就转化成:在整个网页的源码中,找到这样结构的字符串,并将其中的股票代码提取出来。
1.5 编写代码抓取股票代码
编写代码实现urlTolist函数,并在该函数里实现主要的抓取功能:
(1)通过使用urllib.request模块中的urlopen函数访问目的链接;
(2)通过urlopen返回值的read方法获得网页的全部内容;
(3)使用re模块下的compile函数来做正则表达式的计算模版,其模版字符串就是之前分析的网页目标代码;
(4)调用re.compile返回对象的findall方法,来对网页的HTML代码进行正则表达式计算。得到的返回值code便是最终的爬取结果。
代码1:爬取股票代码
01import urllib.request #网络请求模块
import re #正则表达式模块
stock_CodeUrl = '
http://quote.eastmoney.com/stocklist.html' #要爬取的目的地址def urlTolist(url): #获取股票代码列表
allCodeList = []
html = urllib.request.urlopen(url).read() #请求链接,获取网页
html = html.decode('gbk') #转码
s = r'<li><a target="_blank" href="http://quote.eastmoney.com/SS(.*?).html">'
pat = re.compile(s) #创建正则表达式模版
code = pat.findall(html) #正则表达式计算
for item in code:
if item[0]=='6' or item[0]=='3' or item[0]=='0':
allCodeList.append(item)
return allCodeList #返回结果
if __name__=='__main__':
allCodelist = urlTolist(stock_CodeUrl) #调用函数
print(allCodelist[:10]) #显示前10条数据
在上面代码中,函数urlTolist的最后4行代码是为了让结果更加有效而做的数值验证。即,只有6(上海证交所)、0(深圳证交所)、3(创业板)打头的股票代码是有效代码。
在代码中,正则表达式的模版部分(代码中的第9行),有这么一段代码“SS(.*?)”。其中,两个“S”表明每个股票代码的前两个都是字符,是要跳过的地方。后面的括号及里面的内容,表示需要让正则表达式来抓取的部分。(关于正则表达式,不在本书介绍的内容之内,有兴趣的读者可以自行研究。不了解也没关系,直接这么使用即可。)
1.6 运行代码,显示结果
代码运行后,显示如下内容
['600000', '600001', '600002', '600003', '600004', '600005', '600006', '600007', '600008', '600009']
可以看到,爬取的结果是以list的方式存放的。前10条都是上海证交所的股票。
2 爬取股票内容通过访问网易提供的服务接口,可以获取到股票内容。只需按照其提供的请求格式,传入股票代码及所要查看的时间段,即可得到该股票的具体数据。
为了爬取全部数据,需要遍历所有的股票代码,并调用网易的服务接口。
2.1 编写代码抓取批量内容
在代码实现上,仍然使用urllib.request模块进行网络请求,并将调用urllib.request模块下的urlretrieve函数,将返回的数据保存到Excel表里。代码如下:
代码2:爬取股票内容
import urllib.request #网络请求模块
getstocklist = __import__("11-1 爬取股票代码") #导入自定义模块
urlTolist = getstocklist.urlTolist
stock_CodeUrl = '
http://quote.eastmoney.com/stocklist.html' #爬取股票代码的目的地址start = '20161131' #设置查询股票的时间段
end='20161231'
allCodelist = urlTolist(stock_CodeUrl) #获得全部股票代码
for code in allCodelist: #遍历全部代码,调用163接口获得数据
print('正在获取%s股票数据...'%code)
if code[0]=='6':
url = 'http://quotes.money.163.com/service/chddata.html?code=0'+code+
'&start='+start+'&end='+end+'&fields=TCLOSE;HIGH;LOW;TOPEN;LCLOSE;CHG;PCHG;TURNOVER;VOTURNOVER;VATURNOVER;TCAP;MCAP'
else:
url = 'http://quotes.money.163.com/service/chddata.html?code=1'+code+
'&start='+start+'&end='+end+'&fields=TCLOSE;HIGH;LOW;TOPEN;LCLOSE;CHG;PCHG;TURNOVER;VOTURNOVER;VATURNOVER;TCAP;MCAP'
urllib.request.urlretrieve(url,'d:\all_stock_data\'+code+'_'+end+'.csv') #保存到Excel
代码中,设置的时间段为1个月,即从20161131到20161231。
保存的结果放在D盘的all_stock_data路径下。为了保证保存操作正常运行,需要确保D盘下存在all_stock_data文件夹(若没有,需要创建一个)。
2.2 运行代码显示结果
运行代码,输出如下结果:
正在获取600000股票数据...
正在获取600001股票数据...
正在获取600002股票数据...
正在获取600003股票数据...
正在获取600004股票数据...
正在获取600005股票数据...
正在获取600006股票数据...
正在获取600007股票数据...
正在获取600008股票数据...
正在获取600009股票数据...
正在获取600010股票数据...
正在获取600011股票数据...
……
代码运行结束之后,可以D盘的all_stock_data文件夹下找到生成的股票数据文件。
股票数据文件
至此,爬取股票数据的案例就结束了。读者可以根据上面的知识,在网上爬取更多自己需要的内容。另外,爬取的结果还可以保存到MySQL或其他类型文件中。
本文选自以《Python带我起飞——入门、进阶、实战》一书,作者李金洪,电子工业出版社2018年7月出版。本书采用“教学视频+ 图书+ QQ群交流、答疑”三维学习方案,让Python学习更轻松。
上次制作了输入股票代码,显示股票行情、历史数据、股评词云图的网页,但是,想要判断一只股票的投资价值仅看它自己的历史走势是不够的,还要与其他个股尤其是同行业个股进行比较。当然,行业轮动时选对行业是投资成功的第一步,那么如何在对的行业里优中选优?亦或在错的行业中避免错上加错?因此,有必要进行不同行业特征,以及同行业中不同个股之间的比较。
炒股软件虽然提供了各行业股票行情,但是缺少个性化指标的分析,所以把各行业的股票信息分别爬取下来,以便后续分析。
首先,打开东方财富网行情中心网页,可以看到所有行业共分4页,每页有20个行业。
我们需要获取的是各个行业的详情页,即点击行业名称后跳转到该行业个股列表的详情数据。通过该网页前端源代码可以看到行业名称元素对应于一个网址,标签为'href',这就是我们首先要点击进入的网址。定义函数get_url()获取这一网址,即各行业股票列表网址,并存储到字典url_dic中。
def get_url(): #获取各行业股票列表网址 url_dic = {} browser=webdriver.Chrome('D:/chromedriver') browser.get("http://quote.eastmoney.com/center/boardlist.html#industry_board") time.sleep(1) for i in range(1,5): inputpage = browser.find_element_by_css_selector('.paginate_input') inputpage.clear() inputpage.send_keys(str(i)) inputclick = browser.find_element_by_css_selector('.paginte_go') inputclick.click() time.sleep(1) hangye = browser.find_element_by_css_selector('table#table_wrapper-table>tbody') tr_contents = hangye.find_elements_by_tag_name('tr') for tr in tr_contents: td = tr.find_elements_by_css_selector('td:nth-child(2)') for tdd in td: hre = tdd.find_elements_by_tag_name('a') # print(tdd.text) for h in hre: href = h.get_attribute('href') # print(href) url_dic[tdd.text] = href # print(url_dic) browser.close() return url_dic
然后,点击某个行业(如“贵金属”),可以进入该行业详情页。将详情页下拉,可以看到下图所示的个股信息。但是这里的个股是不全的,需要点击“更多”获取该行业全部信息。
实际上,不难发现行业详情页的网址url和点击“更多”后跳转到的该行业全部股票列表网址存在部分相同,股票列表网址可以表示为
'http://data.eastmoney.com/bkzj/'+url[-6:]+'.html'
因此不需要进行模拟点击“更多”的操作,只需获取各行业详情页网址就可以直接编辑股票列表详情页并直接跳转。
进入全部股票列表页面后,还有一个问题,就是不同行业个股数量不同,总页面数也不同。比如,贵金属行业个股一共只有15只,只有一页即可放下,而软件服务行业个股有200只,共有4页(如下图)。所以,需要用专门的函数get_total_page(url)获取不同行业的股票页数。
这里有个坑,当总页数超过5页时,需要加入下面代码中的elif 判断语句,将全部页面加载出来后,再载计算总页数,否则会将总页数误认为只有5页。
def get_total_page(url): #获取某行业股票总页数 # browser=webdriver.Chrome('D:/chromedriver') # browser.get(url) # time.sleep(1) inputpage = browser.find_element_by_css_selector('#PageCont') # print(inputpage.text) pa = re.findall(r'd+',inputpage.text) print(pa) if len(pa)==0: # browser.close() return 1 elif len(pa)==5: nextclick = browser.find_element_by_css_selector('.next') nextclick.click() pa1 = re.findall(r'd+',inputpage.text) return len(pa1) else: return len(pa)
下面定义获取每页股票信息的函数get_perpage_stock()
def get_perpage_stock(): #获取每页股票具体数据 # browser=webdriver.Chrome('D:/chromedriver') # browser.get(url) time.sleep(1) element = browser.find_element_by_css_selector('#dt_1') tr_contents = element.find_elements_by_tag_name('tr') dat = [] for tr in tr_contents: lis = [] for td in tr.find_elements_by_tag_name('td'): lis.append(td.text) dat.append(lis) return dat
有了上面两个函数,即可定义获取各行业全部股票数据的函数get_all_stock(),将各行业全部股票保存到字典 all_data
def get_all_stock(): for i,url in enumerate(dic.values()): url_tar = 'http://data.eastmoney.com/bkzj/'+url[-6:]+'.html' print(url_tar) dat =[] stock_data = [] all_data = {} browser.get(url_tar) wait = WebDriverWait(browser,10,0.5) wait.until(EC.presence_of_element_located((By.ID,"dt_1"))) total_page = get_total_page(url_tar) print('该行业股票总页数为{}'.format(total_page)) if total_page==1: print('正在爬取{}行业股票数据'.format(list(dic.keys())[i])) time.sleep(3) d = get_perpage_stock() d = d[2:] print(d) all_data[list(dic.keys())[i]] = d # browser.close() else: for page in range(1,total_page+1): dat =[] time.sleep(1) inpupage = browser.find_element_by_css_selector('#PageContgopage') inpupage.clear() inpupage.send_keys(page) inpuclick = browser.find_element_by_css_selector('.btn_link') inpuclick.click() time.sleep(1) print('正在爬取{}行业第{}页股票数据'.format(list(dic.keys())[i],page)) time.sleep(3) dat = get_perpage_stock() dat = dat[2:] stock_data.append(dat) print(stock_data) all_data[list(dic.keys())[i]] = stock_data return all_data
爬取过程如下图,
全部代码可关注微信公众号“朋友不发圈”获取(经测试无误,可直接运行),整个程序耗时924.52秒。
# -*- coding: utf-8 -*- """ Created on Sat Jul 4 08:05:26 2020 @author: z """