当前位置: 首页 > 科技观察

Python爬虫实战:股票数据定向爬虫

时间:2023-03-16 12:46:17 科技观察

功能介绍目标:获取沪深两市所有股票的名称及成交信息。输出:保存到文件。技术路线:requests—bs4–re语言:python3.5说明选站原则:股票信息静态存在于html页面,非js代码生成,无Robbts协议限制。选择方法:打开网页,查看源代码,搜索源代码中是否存在网页上的股价数据。例如打开新浪股票网站:链接说明(http://finance.sina.com.cn/realstock/company/sz000877/nc.shtml),如下图:上图左边是网页界面,显示天山股份股价为13.06。右边是网页的源码,查询13.06的源码也没有找到。所以判断网页的数据是js生成的,不适合本项目。于是换网页。然后打开百度股票的网址:链接说明(https://gupiao.baidu.com/stock/sz300023.html),如下图:从上图可以发现百度股票的数据是html代码生成的,符合我们这个项目的要求,所以在这个项目中选择百度股票的网址。由于百度股票只有单只股票的信息,还需要当前股市所有股票的列表。这里我们选择东方财富网,网址为:链接说明(http://quote.eastmoney.com/stocklist.html),界面如下图所示:原理分析查看百度股票中每只股票的网址:https://gupiao.baidu.com/stock/sz300023.html,可以发现网址中有一个数字300023,正是这只股票的编号,sz由深交所代指。因此,我们构建的程序结构如下:第一步:从东方财富网获取股票列表;第二步:一一获取股票代码,加入百度股票链接,***一一访问这些链接获取股票信息;第3步:将结果存储到文件中。然后查看百度个股信息网页源码,发现每只股票的信息存储在html代码中如下:所以我们在存储每只股票信息时,可以参考html的存储方式上图中的代码。每个信息源对应一个信息值,以键值对的形式存储。python中的键值对可以使用字典类型。所以在本项目中,先用字典来存储每只股票的信息,然后再用字典来记录所有股票的信息,最后将字典中的数据输出到文件中。写代码首先是一个获取html网页数据的程序。这里就不介绍了。代码如下:#获取html文本defgetHTMLText(url):try:r=requests.get(url)r.raise_for_status()r.encoding=r.apparent_encodingreturnr.textexcept:return""接下来是html代码解析程序,这里首先需要解析的是Eastmoney网站页面:链接描述(http://quote.eastmoney.com/stocklist.html),我们打开它的源代码如下图:Ascan从上图可以看出,a标签的href属性中的URL链接中包含了每只股票对应的编号,所以我们只需要解析出URL中对应的股票编号即可。解析步骤如下:第一步,获取一个页面:html=getHTMLText(stockURL)第二步,解析页面,找到所有a标签:soup=BeautifulSoup(html,'html.parser')a=soup.find_all('a')第三步,遍历每一个a标签,进行相关处理。处理过程如下:1、找到a标签中的href属性,判断属性中间的链接,取出链接后面的数字,这里可以用正则表达式匹配。由于深交所代码以sz开头,上交所代码以sh开头,股号由6位数字组成,所以正则表达式可以写成[s][hz]\d{6}.也就是说,构造一个正则表达式,在链接中找到一个满足正则表达式的字符串,提取出来。代码如下:foriina:href=i.attrs['href']lst.append(re.findall(r"[s][hz]\d{6}",href)[0])2.因为在html中有很多a标签,但是有些a标签没有href属性,所以上面的程序在运行的时候会出现异常。以上所有程序都需要尝试...除了处理程序的异常。代码如下:foriina:try:href=i.attrs['href']lst.append(re.findall(r"[s][hz]\d{6}",href)[0])except:continue从上面的代码可以看出,对于异常,我们使用continue语句,让它直接跳过,继续执行后面的语句。通过以上程序,我们就可以保存东方财富在线的所有股票代码信息。将上述代码封装成一个函数,解析东方财富网站页面的完整代码如下:defgetStockList(lst,stockURL):html=getHTMLText(stockURL)soup=BeautifulSoup(html,'html.parser')a=汤.find_all('a')foriina:try:href=i.attrs['href']lst.append(re.findall(r"[s][hz]\d{6}",href)[0])except:continue接下来就是从百度股票网链接说明(https://gupiao.baidu.com/stock/sz300023.html)中获取单个股票的信息。我们先查看一下页面的源代码,如下图:股票信息存储在上图的html代码中,所以我们需要分析这段html代码。流程如下:1、百度股票网网址为:https://gupiao.baidu.com/stock/某股票信息网址为:https://gupiao.baidu.com/stock/sz300023。html所以只要百度股票网的网址+每只股票的代码就可以了,而每只股票的代码已经在前面的程序getStockList中从东方财富网解析出来了,所以遍历返回的list就可以了通过getStockList函数,代码如下:forstockinlst:url=stockURL+stock+.html"2、获取到url后,需要访问网页获取网页的html代码。程序如下:html=getHTMLText(url)3.获取到html代码后,需要分析html代码从上图我们可以看出,标签的html代码中存放的是一只股票的信息是div,属性是stock-bets,所以解析为:soup=BeautifulSoup(html,'html.parser')stockInfo=soup。find('div',attrs={'class':'stock-bets'})4.我们发现股票名称在bets-name标签中,继续解析存入字典:infoDict={}name=库存信息。find_all(attrs={'class':'bets-name'})[0]infoDict.update({'stockname':name.text.split()[0]})split()表示股票名称空间的后半部分是不必要的。5、我们从html代码中还可以观察到,dt和dd标签中存储了其他股票信息,其中dt代表股票信息的key字段,dd标签为value字段。获取所有的键和值:keyList=stockInfo.find_all('dt')valueList=stockInfo.find_all('dd')将获取到的键和值以键值对的形式放入字典中:foriinrange(len(keyList)):key=keyList[i].textval=valueList[i].textinfoDict[key]=val6.***将字典中的数据存储到外部文件中:withopen(fpath,'a',encoding='utf-8')asf:f.write(str(infoDict)+'\n')将上述过程封装成一个完成的函数,代码如下:defgetStockInfo(lst,stockURL,fpath):forstockinlst:url=stockURL+stock+".html"html=getHTMLText(url)try:ifhtml=="":continueinfoDict={}soup=BeautifulSoup(html,'html.parser')stockInfo=soup.find('div',attrs={'class':'stock-bets'})name=stockInfo.find_all(attrs={'class':'bets-name'})[0]infoDict.update({'stockname':name.text.split()[0]})keyList=stockInfo.find_all('dt')valueList=stockInfo.find_all('dd')foriinrange(len(keyList)):key=keyList[i].textval=valueList[i].textinfoDict[key]=valwithopen(fpath,'a',encoding='utf-8')asf:f.write(str(infoDict)+'\n')except:continue其中try...except用于异常处理。接下来来编写主函数,调用上记函数即可:defmain():stock_list_url='http://quote.eastmoney.com/stocklist.html'stock_info_url='https://gupiao.baidu.com/stock/'output_file='D:/BaiduStockInfo.txt'slist=[]getStockList(slist,stock_list_url)getStockInfo(slist,stock_info_url,output_file)项目完成流程#-*-coding:utf-8-*-importrequestsfrombs4importBeautifulSoupimporttracebackimportredefgetHTMLText(url):try:r=requests.get(url)r.raise_for_status()r.encoding=r.apparent_encodingreturnr.textexcept:return""defgetStockList(lst,stockURL):html=getHTMLText(stockURL)soup=BeautifulSoup(html,'html.parser')a=soup.find_all('a')foriina:try:href=i.attrs['href']lst.append(re.findall(r"[s][hz]\d{6}",href)[0])除了:continuedefgetStockInfo(lst,stockURL,fpath):count=0forstockinlst:url=stockURL+stock+".html"html=getHTMLText(url)try:ifhtml=="":continueinfoDict={}soup=BeautifulSoup(html,'html.parser')stockInfo=soup.find('div',attrs={'class':'stock-bets'})name=stockInfo.find_all(attrs={'class':'bets-name'})[0]infoDict.update({'stockname':name.text.split()[0]})keyList=stockInfo.find_all('dt')valueList=stockInfo.find_all('dd')foriinrange(len(keyList)):key=keyList[i].textval=valueList[i].textinfoDict[key]=valwithopen(fpath,'a',encoding='utf-8')asf:f.write(str(infoDict)+'\n')count=count+1print("\rcurrentprogress:{:.2f}%".format(count*100/len(lst)),end="")except:count=count+1print("\rcurrentprogress:{:.2f}%".format(count*100/len(lst)),end="")continuedefmain():stock_list_url='http://quote.eastmoney.com/stocklist.html'stock_info_url='https://gupiao.baidu.com/stock/'output_file='D:/BaiduStockInfo.txt'slist=[]getStockList(slist,stock_list_url)getStockInfo(slist,stock_info_url,output_file)main()上面代码中的print语句是用来打印爬虫进度的执行上面代码后,D盘会出现一个BaiduStockInfo.txt文件,里面存放的是股票信息。