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

简介:

功能简介

  • 目标: 获取上交所和深交所所有股票的名称和交易信息。
  • 输出: 保存到文件中。
  • 技术路线: 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表示的深圳交易所。因此我们构造的程序结构如下:

  • 步骤1: 从东方财富网获取股票列表;
  • 步骤2: 逐一获取股票代码,并增加到百度股票的链接中,最后对这些链接进行逐个的访问获得股票的信息;
  • 步骤3: 将结果存储到文件。

接着查看百度个股信息网页的源代码,发现每只股票的信息在html代码中的存储方式如下:

因此,在我们存储每只股票的信息时,可以参考上图中html代码的存储方式。每一个信息源对应一个信息值,即采用键值对的方式进行存储。在python中键值对的方式可以用字典类型。因此,在本项目中,使用字典来存储每只股票的信息,然后再用字典把所有股票的信息记录起来,最后将字典中的数据输出到文件中。

代码编写

首先是获得html网页数据的程序,在这里不多做介绍了,代码如下:

 
  1. #获得html文本 
  2.  
  3. def getHTMLText(url): 
  4.  
  5.     try: 
  6.  
  7.         r = requests.get(url) 
  8.  
  9.         r.raise_for_status() 
  10.  
  11.         r.encoding = r.apparent_encoding 
  12.  
  13.         return r.text 
  14.  
  15.     except
  16.  
  17.         return ""  

接下来是html代码解析程序,在这里首先需要解析的是东方财富网页面:链接描述(http://quote.eastmoney.com/stocklist.html),我们打开其源代码,如下图所示:

由上图可以看到,a标签的href属性中的网址链接里面有每只股票的对应的号码,因此我们只要把网址里面对应股票的号码解析出来即可。解析步骤如下:

第一步,获得一个页面:

 
  1. html = getHTMLText(stockURL) 

第二步,解析页面,找到所有的a标签:

 
  1. soup = BeautifulSoup(html, 'html.parser'
  2.  
  3. a = soup.find_all('a')  

第三步,对a标签中的每一个进行遍历来进行相关的处理。处理过程如下:

1.找到a标签中的href属性,并且判断属性中间的链接,把链接后面的数字取出来,在这里可以使用正则表达式来进行匹配。由于深圳交易所的代码以sz开头,上海交易所的代码以sh开头,股票的数字有6位构成,所以正则表达式可以写为[s][hz]\d{6}。也就是说构造一个正则表达式,在链接中去寻找满足这个正则表达式的字符串,并把它提取出来。代码如下:

 
  1. for i in a: 
  2.  
  3.     href = i.attrs['href'
  4.  
  5.     lst.append(re.findall(r"[s][hz]\d{6}", href)[0])  

2.由于在html中有很多的a标签,但是有些a标签中没有href属性,因此上述程序在运行的时候出现异常,所有对上述的程序还要进行try…except来对程序进行异常处理,代码如下:

 
  1. for i in a: 
  2.  
  3.     try: 
  4.  
  5.         href = i.attrs['href'
  6.  
  7.         lst.append(re.findall(r"[s][hz]\d{6}", href)[0]) 
  8.  
  9.     except
  10.  
  11.         continue  

从上面代码可以看出,对于出现异常的情况我们使用了continue语句,直接让其跳过,继续执行下面的语句。通过上面的程序我们就可以把东方财富网上股票的代码信息全部保存下来了。

将上述的代码封装成一个函数,对东方财富网页面解析的完整代码如下所示:

 
  1. def getStockList(lst, stockURL): 
  2.  
  3.     html = getHTMLText(stockURL) 
  4.  
  5.     soup = BeautifulSoup(html, 'html.parser'
  6.  
  7.     a = soup.find_all('a'
  8.  
  9.     for i in a: 
  10.  
  11.         try: 
  12.  
  13.             href = i.attrs['href'
  14.  
  15.             lst.append(re.findall(r"[s][hz]\d{6}", href)[0]) 
  16.  
  17.         except
  18.  
  19.             continue  

接下来是获得百度股票网链接描述(https://gupiao.baidu.com/stock/sz300023.html)单只股票的信息。我们先查看该页面的源代码,如下图所示:

股票的信息就存在上图所示的html代码中,因此我们需要对这段html代码进行解析。过程如下:

1.百度股票网的网址为:https://gupiao.baidu.com/stock/

一只股票信息的网址为:https://gupiao.baidu.com/stock/sz300023.html

所以只要百度股票网的网址+每只股票的代码即可,而每只股票的代码我们已经有前面的程序getStockList从东方财富网解析出来了,因此对getStockList函数返回的列表进行遍历即可,代码如下:

 
  1. for stock in lst: 
  2.  
  3. url = stockURL + stock + ".html"  

2.获得网址后,就要访问网页获得网页的html代码了,程序如下:

 
  1. html = getHTMLText(url) 

3.获得了html代码后就需要对html代码进行解析,由上图我们可以看到单个股票的信息存放在标签为div,属性为stock-bets的html代码中,因此对其进行解析:

 
  1. soup = BeautifulSoup(html, 'html.parser'
  2.  
  3. stockInfo = soup.find('div',attrs={'class':'stock-bets'}) 

4.我们又发现股票名称在bets-name标签内,继续解析,存入字典中:

 
  1. infoDict = {} 
  2.  
  3. name = stockInfo.find_all(attrs={'class':'bets-name'})[0] 
  4.  
  5. infoDict.update({'股票名称'name.text.split()[0]})  

split()的意思是股票名称空格后面的部分不需要了。

5.我们从html代码中还可以观察到股票的其他信息存放在dt和dd标签中,其中dt表示股票信息的键域,dd标签是值域。获取全部的键和值:

 
  1. keyList = stockInfo.find_all('dt'
  2.  
  3. valueList = stockInfo.find_all('dd')  

并把获得的键和值按键值对的方式村放入字典中:

 
  1. for i in range(len(keyList)): 
  2.  
  3. key = keyList[i].text 
  4.  
  5. val = valueList[i].text 
  6.  
  7. infoDict[key] = val  

6.最后把字典中的数据存入外部文件中:

 
  1. with open(fpath, 'a', encoding='utf-8'as f: 
  2.  
  3. f.write( str(infoDict) + '\n' )  

将上述过程封装成完成的函数,代码如下:

 
  1. def getStockInfo(lst, stockURL, fpath): 
  2.  
  3.     for stock in lst: 
  4.  
  5.         url = stockURL + stock + ".html" 
  6.  
  7.         html = getHTMLText(url) 
  8.  
  9.         try: 
  10.  
  11.             if html==""
  12.  
  13.                 continue 
  14.  
  15.             infoDict = {} 
  16.  
  17.             soup = BeautifulSoup(html, 'html.parser'
  18.  
  19.             stockInfo = soup.find('div',attrs={'class':'stock-bets'}) 
  20.  
  21.             name = stockInfo.find_all(attrs={'class':'bets-name'})[0] 
  22.  
  23.             infoDict.update({'股票名称'name.text.split()[0]}) 
  24.  
  25.              
  26.  
  27.             keyList = stockInfo.find_all('dt'
  28.  
  29.             valueList = stockInfo.find_all('dd'
  30.  
  31.             for i in range(len(keyList)): 
  32.  
  33.                 key = keyList[i].text 
  34.  
  35.                 val = valueList[i].text 
  36.  
  37.                 infoDict[key] = val 
  38.  
  39.              
  40.  
  41.             with open(fpath, 'a', encoding='utf-8'as f: 
  42.  
  43.                 f.write( str(infoDict) + '\n' ) 
  44.  
  45.         except
  46.  
  47.             continue  

其中try…except用于异常处理。

接下来编写主函数,调用上述函数即可:

 
  1. def main(): 
  2.  
  3.     stock_list_url = 'http://quote.eastmoney.com/stocklist.html' 
  4.  
  5.     stock_info_url = 'https://gupiao.baidu.com/stock/' 
  6.  
  7.     output_file = 'D:/BaiduStockInfo.txt' 
  8.  
  9.     slist=[] 
  10.  
  11.     getStockList(slist, stock_list_url) 
  12.  
  13.     getStockInfo(slist, stock_info_url, output_file)  

项目完整程序

 
  1. # -*- coding: utf-8 -*- 
  2.  
  3.   
  4.  
  5. import requests 
  6.  
  7. from bs4 import BeautifulSoup 
  8.  
  9. import traceback 
  10.  
  11. import re 
  12.  
  13. def getHTMLText(url): 
  14.  
  15.     try: 
  16.  
  17.         r = requests.get(url) 
  18.  
  19.         r.raise_for_status() 
  20.  
  21.         r.encoding = r.apparent_encoding 
  22.  
  23.         return r.text 
  24.  
  25.     except
  26.  
  27.         return "" 
  28.  
  29. def getStockList(lst, stockURL): 
  30.  
  31.     html = getHTMLText(stockURL) 
  32.  
  33.     soup = BeautifulSoup(html, 'html.parser'
  34.  
  35.     a = soup.find_all('a'
  36.  
  37.     for i in a: 
  38.  
  39.         try: 
  40.  
  41.             href = i.attrs['href'
  42.  
  43.             lst.append(re.findall(r"[s][hz]\d{6}", href)[0]) 
  44.  
  45.         except
  46.  
  47.             continue 
  48.  
  49. def getStockInfo(lst, stockURL, fpath): 
  50.  
  51.     count = 0 
  52.  
  53.     for stock in lst: 
  54.  
  55.         url = stockURL + stock + ".html" 
  56.  
  57.         html = getHTMLText(url) 
  58.  
  59.         try: 
  60.  
  61.             if html==""
  62.  
  63.                 continue 
  64.  
  65.             infoDict = {} 
  66.  
  67.             soup = BeautifulSoup(html, 'html.parser'
  68.  
  69.             stockInfo = soup.find('div',attrs={'class':'stock-bets'}) 
  70.  
  71.             name = stockInfo.find_all(attrs={'class':'bets-name'})[0] 
  72.  
  73.             infoDict.update({'股票名称'name.text.split()[0]}) 
  74.  
  75.              
  76.  
  77.             keyList = stockInfo.find_all('dt'
  78.  
  79.             valueList = stockInfo.find_all('dd'
  80.  
  81.             for i in range(len(keyList)): 
  82.  
  83.                 key = keyList[i].text 
  84.  
  85.                 val = valueList[i].text 
  86.  
  87.                 infoDict[key] = val 
  88.  
  89.              
  90.  
  91.             with open(fpath, 'a', encoding='utf-8'as f: 
  92.  
  93.                 f.write( str(infoDict) + '\n' ) 
  94.  
  95.                 count = count + 1 
  96.  
  97.                 print("\r当前进度: {:.2f}%".format(count*100/len(lst)),end=""
  98.  
  99.         except
  100.  
  101.             count = count + 1 
  102.  
  103.             print("\r当前进度: {:.2f}%".format(count*100/len(lst)),end=""
  104.  
  105.             continue 
  106.  
  107. def main(): 
  108.  
  109.     stock_list_url = 'http://quote.eastmoney.com/stocklist.html' 
  110.  
  111.     stock_info_url = 'https://gupiao.baidu.com/stock/' 
  112.  
  113.     output_file = 'D:/BaiduStockInfo.txt' 
  114.  
  115.     slist=[] 
  116.  
  117.     getStockList(slist, stock_list_url) 
  118.  
  119.     getStockInfo(slist, stock_info_url, output_file) 
  120.  
  121. main()  

上述代码中的print语句用于打印爬取的进度。执行完上述代码后在D盘会出现BaiduStockInfo.txt文件,里面存放了股票的信息。


作者:佚名

来源:51CTO

相关文章
|
3天前
|
API 数据库 数据安全/隐私保护
Flask框架在Python面试中的应用与实战
【4月更文挑战第18天】Django REST framework (DRF) 是用于构建Web API的强力工具,尤其适合Django应用。本文深入讨论DRF面试常见问题,包括视图、序列化、路由、权限控制、分页过滤排序及错误处理。同时,强调了易错点如序列化器验证、权限认证配置、API版本管理、性能优化和响应格式统一,并提供实战代码示例。了解这些知识点有助于在Python面试中展现优秀的Web服务开发能力。
20 1
|
1天前
|
机器学习/深度学习 算法 Python
数据分享|Python决策树、随机森林、朴素贝叶斯、KNN(K-最近邻居)分类分析银行拉新活动挖掘潜在贷款客户
数据分享|Python决策树、随机森林、朴素贝叶斯、KNN(K-最近邻居)分类分析银行拉新活动挖掘潜在贷款客户
16 4
|
1天前
|
数据采集 存储 人工智能
【AI大模型应用开发】【LangChain系列】实战案例2:通过URL加载网页内容 - LangChain对爬虫功能的封装
【AI大模型应用开发】【LangChain系列】实战案例2:通过URL加载网页内容 - LangChain对爬虫功能的封装
7 0
|
1天前
|
机器学习/深度学习 算法 算法框架/工具
数据分享|PYTHON用KERAS的LSTM神经网络进行时间序列预测天然气价格例子
数据分享|PYTHON用KERAS的LSTM神经网络进行时间序列预测天然气价格例子
17 0
|
1天前
|
机器学习/深度学习 数据挖掘 网络架构
Python对商店数据进行lstm和xgboost销售量时间序列建模预测分析
Python对商店数据进行lstm和xgboost销售量时间序列建模预测分析
12 0
|
1天前
|
数据挖掘 数据处理 索引
如何使用Python的Pandas库进行数据筛选和过滤?
Pandas是Python数据分析的核心库,提供DataFrame数据结构。基本步骤包括导入库、创建DataFrame及进行数据筛选。示例代码展示了如何通过布尔索引、`query()`和`loc[]`方法筛选`Age`大于19的记录。
10 0
|
2天前
|
机器学习/深度学习 算法 数据挖掘
PYTHON银行机器学习:回归、随机森林、KNN近邻、决策树、高斯朴素贝叶斯、支持向量机SVM分析营销活动数据|数据分享-2
PYTHON银行机器学习:回归、随机森林、KNN近邻、决策树、高斯朴素贝叶斯、支持向量机SVM分析营销活动数据|数据分享
21 1
|
2天前
|
数据采集 存储 JSON
Python爬虫面试:requests、BeautifulSoup与Scrapy详解
【4月更文挑战第19天】本文聚焦于Python爬虫面试中的核心库——requests、BeautifulSoup和Scrapy。讲解了它们的常见问题、易错点及应对策略。对于requests,强调了异常处理、代理设置和请求重试;BeautifulSoup部分提到选择器使用、动态内容处理和解析效率优化;而Scrapy则关注项目架构、数据存储和分布式爬虫。通过实例代码,帮助读者深化理解并提升面试表现。
11 0
|
2天前
|
数据处理 Python
如何使用Python的Pandas库进行数据排序和排名
【4月更文挑战第22天】Pandas Python库提供数据排序和排名功能。使用`sort_values()`按列进行升序或降序排序,如`df.sort_values(by='A', ascending=False)`。`rank()`函数用于计算排名,如`df['A'].rank(ascending=False)`。多列操作可传入列名列表,如`df.sort_values(by=['A', 'B'], ascending=[True, False])`和分别对'A'、'B'列排名。
13 2
|
3天前
|
Python
如何使用Python的Pandas库进行数据缺失值处理?
Pandas在Python中提供多种处理缺失值的方法:1) 使用`isnull()`检查;2) `dropna()`删除含缺失值的行或列;3) `fillna()`用常数、前后值填充;4) `interpolate()`进行插值填充。根据需求选择合适的方法处理数据缺失。
35 9