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月前
|
SQL 关系型数据库 数据库
Python SQLAlchemy模块:从入门到实战的数据库操作指南
免费提供Python+PyCharm编程环境,结合SQLAlchemy ORM框架详解数据库开发。涵盖连接配置、模型定义、CRUD操作、事务控制及Alembic迁移工具,以电商订单系统为例,深入讲解高并发场景下的性能优化与最佳实践,助你高效构建数据驱动应用。
469 7
|
3月前
|
数据采集 Web App开发 数据安全/隐私保护
实战:Python爬虫如何模拟登录与维持会话状态
实战:Python爬虫如何模拟登录与维持会话状态
|
3月前
|
传感器 运维 前端开发
Python离群值检测实战:使用distfit库实现基于分布拟合的异常检测
本文解析异常(anomaly)与新颖性(novelty)检测的本质差异,结合distfit库演示基于概率密度拟合的单变量无监督异常检测方法,涵盖全局、上下文与集体离群值识别,助力构建高可解释性模型。
385 10
Python离群值检测实战:使用distfit库实现基于分布拟合的异常检测
|
3月前
|
数据采集 监控 数据库
Python异步编程实战:爬虫案例
🌟 蒋星熠Jaxonic,代码为舟的星际旅人。从回调地狱到async/await协程天堂,亲历Python异步编程演进。分享高性能爬虫、数据库异步操作、限流监控等实战经验,助你驾驭并发,在二进制星河中谱写极客诗篇。
Python异步编程实战:爬虫案例
|
3月前
|
存储 分布式计算 测试技术
Python学习之旅:从基础到实战第三章
总体来说,第三章是Python学习路程中的一个重要里程碑,它不仅加深了对基础概念的理解,还引入了更多高级特性,为后续的深入学习和实际应用打下坚实的基础。通过这一章的学习,读者应该能够更好地理解Python编程的核心概念,并准备好应对更复杂的编程挑战。
149 12
|
3月前
|
数据采集 存储 JSON
Python爬虫常见陷阱:Ajax动态生成内容的URL去重与数据拼接
Python爬虫常见陷阱:Ajax动态生成内容的URL去重与数据拼接
|
3月前
|
存储 数据采集 监控
Python文件操作全攻略:从基础到高级实战
本文系统讲解Python文件操作核心技巧,涵盖基础读写、指针控制、异常处理及大文件分块处理等实战场景。结合日志分析、CSV清洗等案例,助你高效掌握文本与二进制文件处理,提升程序健壮性与开发效率。(238字)
407 1
|
3月前
|
存储 Java 调度
Python定时任务实战:APScheduler从入门到精通
APScheduler是Python强大的定时任务框架,通过触发器、执行器、任务存储和调度器四大组件,灵活实现各类周期性任务。支持内存、数据库、Redis等持久化存储,适用于Web集成、数据抓取、邮件发送等场景,解决传统sleep循环的诸多缺陷,助力构建稳定可靠的自动化系统。(238字)
680 1
|
3月前
|
Java 调度 数据库
Python threading模块:多线程编程的实战指南
本文深入讲解Python多线程编程,涵盖threading模块的核心用法:线程创建、生命周期、同步机制(锁、信号量、条件变量)、线程通信(队列)、守护线程与线程池应用。结合实战案例,如多线程下载器,帮助开发者提升程序并发性能,适用于I/O密集型任务处理。
378 0
|
3月前
|
机器学习/深度学习 监控 数据挖掘
Python 高效清理 Excel 空白行列:从原理到实战
本文介绍如何使用Python的openpyxl库自动清理Excel中的空白行列。通过代码实现高效识别并删除无数据的行与列,解决文件臃肿、读取错误等问题,提升数据处理效率与准确性,适用于各类批量Excel清理任务。
451 0

推荐镜像

更多