当前位置:   article > 正文

利用python爬虫分析基金、股票_爬虫爬取股票数据并分析

爬虫爬取股票数据并分析

前言:

听说你想要变富?那就沉住气慢慢来吧,没听过这句名言么:“穷人总是不想慢慢的变富”。都想着一夜暴富,中个彩票啥的,可哪有那么幸运呢?总不能像我一样中了78万的彩票,然后自己偷偷的花吧。

想要慢慢的变富有,只要理好财就可以了;小钱靠攒,大钱靠赚!之前我也曾苦于思索如何让自己实现财富自由,所以才有了学习理财的想法,说到理财就不得不说一些理财产品,比如黄金、期货、股票、基金等,先普及一下这些小知识吧,因为就是爬取股票、基金的,所以就简单介绍一下这两者了;

股票(英语:stock)或是资本存货(英语:capital stock)是一种有价证券,股份公司将其所有权借由这种有价证卷进行分配。因为股份公司需要筹集资金,因此将股票发给投资者作为公司资本部分所有权的凭证,成为股东以此获得股息(股利),并分享公司成长或交易市场波动带来的利润;但也要共同承担公司运作错误所带来的风险。

-------来着 维基百科

基金,举个栗子吧,就是你手里有钱,想买股票,但是不懂股票的相关知识;我没钱,但有着非常丰富的金融知识、股票经验,是个理财的好手。于是我们一合计,你把你的钱给我,我来用这些钱理财,等赚钱了我从中拿点分成;“我”指的就是基金;

------来自 星火燎愿 的自我理解

总体来说,股票是收益高,风险也高。基金是收益低,风险也低,因为基金买了好多的股票,买的股票也基本不会遇到全部涨或者全部跌的情况,所以抗风险性比较大。说到这里,假我不想买基金,就想买股票,还想买好的股票,但是我又不懂股票,咋办呢,额,好吧,我就是这么想的,虽然想得美,但是办法总是有的。我们分析下,基金算是买了很多股票的机构,并且里面都是各路财经大神,我们可以从基金里看到它们都买了哪些股票,然后跟着它们买不就ok了么,毕竟它们也不想让自己亏损,会挑选有潜力的股票的。

正文

本文就是利用python对某一财经网站的基金进行了爬取,爬取了5000+个基金所持有的股票,并进行了处理。

前阵因为爬取数据导致整个公司被抓的案例有不少,所以在此说明:拒绝利用爬虫进行违法的行为,坚决爱国爱民,做好事不留名,多扶老奶奶过马路,希望警察叔叔不要因为这篇爬虫文章把me带走。

本文涉及到的知识点:

1、python字符串:分割、拼接、中文字符判断;

2、python正则表达式;

3、爬虫requests请求库、xpath获取数据、代理服务器;

4、selenium用法:无头浏览器、元素定位、显式等待、数据获取;

5、python操作mongodb

网站分析

代码和数据我们到后面再贴上,先来分析下目标网站,这样有利于我们爬取过程更加清晰;

目标网站:开放式基金排行 _ 天天基金网

我们爬取的就是【开放式基金】里的数据:

我们随便点开一个基金,就可以进入其详情页面,不知道你发现没有,该基金详情页面的url就是首页该基金的基金代码和http://fund.eastmoney.com/的一个组合,比如:

040011 --- 华安核心优选混合的url:华安核心优选混合(040011)基金净值_估值_行情走势-天天基金网

005660 --- 嘉实资源精选股票A的url:嘉实资源精选股票A(005660)基金净值_估值_行情走势-天天基金网

ok,好,我们在基金详情页面往下拉就可以找到该基金的股票持仓信息,也就是该基金买了哪些股票:

然后点击 更多 进入该基金持股的详情页,往下拉就会看到,该基金三个季度的股票持仓信息:

对,这就是目标数据,要爬取的数据;

ok,我们先不爬取,再分析这个基金持仓的详情页,这个url也是有规律的,它是用 http://fundf10.eastmoney.com/ccmx_ 和该基金的基金代码组合成的,比如:

005660 ,嘉实资源精选股票A 的持仓详情页面url:嘉实资源精选股票A(005660)基金持仓 _ 基金档案 _ 天天基金网

006921,南方智诚混合 的持仓详情页面url:南方智诚混合(006921)基金持仓 _ 基金档案 _ 天天基金网

因为这些数据是用js动态加载的,如果使用requests爬取的话难度很大,这种情况下一般会使用selenium模拟浏览器行为进行爬取。但是selenium爬取的效率确实比较低。其实我们依旧是可以使用requests进行爬取的,js动态加载是html页面中的js代码执行了一段操作,从服务端自动加载了数据,所以数据在一开始爬取的页面上是看不到的,除非一些特别难爬的数据才需要selenium,因为selenium号称:只要是你看得到的数据就都可以获取。毕竟selenium是模仿人操作浏览器的行为的。这里我们分析js动态加载,然后利用requests来爬取,后面进行二次爬取的时候再用selenium。

在首页按F12打开开发者工具,然后再刷新一下,

可以看到右边蓝色框里的数据了吧,这是js动态加载之后返回的数据,然后经过加工后呈现在页面上的,其实只要获取这些数据就可以了,不用去爬取首页了;

我们再点击 Headers ,这个 Request URL 就是js请求的url了,你可以试试把这个url直接用浏览器回车下,会给你返回一堆的数据;上面分析了基金持仓股票页面url的组成,所以只要需要这些数据里的六位基金代码就可以了,本篇代码中是用python正则进行了六位数字的提取,然后组成的基金持仓股票页面的url;然后再在基金持仓股票页面对该基金持有的股票进行爬取、存储;

爬取流程:

1、首先从首页中请求js动态加载数据时请求的那个url,从中获取六位数字的基金代码,

然后 http://fundf10.eastmoney.com/ccmx_ + 基金代码 + .html 组成的基金持仓股票的详情页url;

2、针对 基金持仓股票的详情页url 进行爬取,因为也是js动态加载的(加载速度较快),并且需要判断该基金是否有持仓的股票(有的基金没有买股票,也不知道他们干啥了),所以使用selenium来爬取,同时也使用了显式等待的方式来等待数据加载完成;

3、将数据整理,存储到mongodb中;

代码讲解---数据爬取:

这次我们将代码分段放上来,分段说明;

需要的库:

  1. import requests
  2. import re
  3. from lxml import etree
  4. from selenium import webdriver
  5. from selenium.webdriver.chrome.options import Options
  6. from selenium.webdriver.common.by import By
  7. from selenium.webdriver.support.ui import WebDriverWait
  8. from selenium.webdriver.support import expected_conditions as EC
  9. import pymongo

准备一些常用的方法:

  1. #判断字符串中是否含有中文
  2. def is_contain_chinese(check_str):
  3. """
  4. 判断字符串中是否包含中文
  5. :param check_str: {str} 需要检测的字符串
  6. :return: {bool} 包含返回True, 不包含返回False
  7. """
  8. for ch in check_str:
  9. if u'\u4e00' <= ch <= u'\u9fff':
  10. return True
  11. return False
  12. #selenium通过class name判断元素是否存在,用于判断基金持仓股票详情页中该基金是否有持仓股票;
  13. def is_element(driver,element_class):
  14. try:
  15. WebDriverWait(driver,2).until(EC.presence_of_element_located((By.CLASS_NAME,element_class)))
  16. except:
  17. return False
  18. else:
  19. return True
  20. #requests请求url的方法,处理后返回text文本
  21. def get_one_page(url):
  22. headers = {
  23. 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36',
  24. }
  25. proxies = {
  26. "http": "http://XXX.XXX.XXX.XXX:XXXX"
  27. }
  28. response = requests.get(url,headers=headers,proxies=proxies)
  29. response.encoding = 'utf-8'
  30. if response.status_code == 200:
  31. return response.text
  32. else:
  33. print("请求状态码 != 200,url错误.")
  34. return None
  35. #该方法直接将首页的数据请求、返回、处理,组成持仓信息url和股票名字并存储到数组中;
  36. def page_url():
  37. stock_url = [] #定义一个数组,存储基金持仓股票详情页面的url
  38. stock_name = [] #定义一个数组,存储基金的名称
  39. url = "http://fund.eastmoney.com/data/rankhandler.aspx?op=ph&dt=kf&ft=all&rs=&gs=0&sc=zzf&st=desc&sd=2018-11-26&ed=2019-11-26&qdii=&tabSubtype=,,,,,&pi=1&pn=10000&dx=1&v=0.234190661250681"
  40. result_text = get_one_page(url)
  41. # print(result_text.replace('\"',',')) #将"替换为,
  42. # print(result_text.replace('\"',',').split(',')) #以,为分割
  43. # print(re.findall(r"\d{6}",result_text)) #输出股票的6位代码返回数组;
  44. for i in result_text.replace('\"',',').split(','): #将"替换为,再以,进行分割,遍历筛选出含有中文的字符(股票的名字)
  45. result_chinese = is_contain_chinese(i)
  46. if result_chinese == True:
  47. stock_name.append(i)
  48. for numbers in re.findall(r"\d{6}",result_text):
  49. stock_url.append("http://fundf10.eastmoney.com/ccmx_%s.html" % (numbers)) #将拼接后的url存入列表;
  50. return stock_url,stock_name
  51. #selenium请求[基金持仓股票详情页面url]的方法,爬取基金的持仓股票名称;
  52. def hold_a_position(url):
  53. driver.get(url) # 请求基金持仓的信息
  54. element_result = is_element(driver, "tol") # 是否存在这个元素,用于判断是否有持仓信息;
  55. if element_result == True: # 如果有持仓信息则爬取;
  56. wait = WebDriverWait(driver, 3) # 设置一个等待时间
  57. input = wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'tol'))) # 等待这个class的出现;
  58. ccmx_page = driver.page_source # 获取页面的源码
  59. ccmx_xpath = etree.HTML(ccmx_page) # 转换成成 xpath 格式
  60. ccmx_result = ccmx_xpath.xpath("//div[@class='txt_cont']//div[@id='cctable']//div[@class='box'][1]//td[3]//text()")
  61. return ccmx_result
  62. else: #如果没有持仓信息,则返回null字符;
  63. return "null"

注意 page_url() 方法,里面的url就是上面分析js动态加载数据时请求的url,需要注意的是该url后面的参数,pi是第几页,pn是每页多少条数据,我这里pi=1,pn=10000,意思就是第一页,显示10000条数据(实际数据肯定没这么多,首页才5000+),就一次性的显示出所有的数据了;

程序开始:

  1. if __name__ == '__main__':
  2. # 创建连接mongodb数据库
  3. client = pymongo.MongoClient(host='XXX.XXX.XXX.XXX', port=XXXXX) # 连接mongodb,host是ip,port是端口
  4. db = client.db_spider # 使用(创建)数据库
  5. db.authenticate("用户名", "密码") # mongodb的用户名、密码连接;
  6. collection = db.tb_stock # 使用(创建)一个集合(表)
  7. stock_url, stock_name = page_url() #获取首页数据,返回基金url的数组和基金名称的数组;
  8. #浏览器动作
  9. chrome_options = Options()
  10. chrome_options.add_argument('--headless')
  11. driver = webdriver.Chrome(options=chrome_options) #初始化浏览器,无浏览器界面的;
  12. if len(stock_url) == len(stock_name): #判断获取的基金url和基金名称数量是否一致
  13. for i in range(len(stock_url)):
  14. return_result = hold_a_position(stock_url[i]) # 遍历持仓信息,返回持仓股票的名称---数组
  15. dic_data = {
  16. 'fund_url':stock_url[i],
  17. 'fund_name':stock_name[i],
  18. 'stock_name':return_result
  19. } #dic_data 为组成的字典数据,为存储到mongodb中做准备;
  20. print(dic_data)
  21. collection.insert_one(dic_data) #将dic_data插入mongodb数据库
  22. else:
  23. print("基金url和基金name数组数量不一致,退出。")
  24. exit()
  25. driver.close() #关闭浏览器
  26. #查询:过滤出非null的数据
  27. find_stock = collection.find({'stock_name': {'$ne': 'null'}}) # 查询 stock_name 不等于 null 的数据(排除那些没有持仓股票的基金机构);
  28. for i in find_stock:
  29. print(i)

好,至此,爬取数据的代码交代完毕,运行后坐等即可;

该项目单进程运行,所以爬取速度略慢,同时也受网速影响,后期会继续改进成多线程。

代码讲解---数据处理:

上面已经把数据爬取并存储到数据库中,这里对数据进行处理,将其变成可用的;

首先说明思路:

1、我们需要知道这些基金所有持仓的股票的综合数据,也包括基金持仓中有重复的股票;

2、需要知道哪些股票重复了,有多少个重复的,重复了多少次;

这样,重复数最多的那只股票就肯定是最好的了,因为这证明有很多的基金都购买了这支股票;

具体看代码,注释说的已经很清楚了:

  1. import pymongo
  2. #一、数据库:连接库、使用集合、创建文档;#
  3. client = pymongo.MongoClient(host='XXX.XXX.XXX.XXX',port=XXXXX) #连接mongodb数据库
  4. db = client.db_spider #使用(创建)数据库
  5. db.authenticate("用户名","密码") #认证用户名、密码
  6. collection = db.tb_stock #使用(创建)一个集合(表),里面已经存储着上面程序爬取的数据了;
  7. tb_result = db.tb_data #使用(创建)一个集合(表),用于存储最后处理完毕的数据;
  8. #查询 stock_name 不等于 null 的数据,即:排除那些没有持仓股票的基金;
  9. find_stock = collection.find({'stock_name':{'$ne':'null'}})
  10. #二、处理数据,将所有的股票数组累加成一个数组---list_stock_all #
  11. list_stock_all = [] #定义一个数组,存储所有的股票名称,包括重复的;
  12. for i in find_stock:
  13. print(i['stock_name']) #输出基金的持仓股票(类型为数组)
  14. list_stock_all = list_stock_all + i['stock_name'] #综合所有的股票数组为一个数组;
  15. print("股票总数:" + str(len(list_stock_all)))
  16. #三、处理数据,股票去重#
  17. list_stock_repetition = [] #定义一个数组,存放去重之后的股票
  18. for n in list_stock_all:
  19. if n not in list_stock_repetition: #如果不存在
  20. list_stock_repetition.append(n) #则添加进该数组,去重;
  21. print("去重后的股票数量:" + str(len(list_stock_repetition)))
  22. #四、综合二、三中的得出的两个数组进行数据筛选#
  23. for u in list_stock_repetition: #遍历去重后股票的数组
  24. if list_stock_all.count(u) > 10: #在未去重股票的数组中查找股票的重复数,如果重复数大于10
  25. #将数据组成字典,用于存储到mongodb中;
  26. data_stock = {
  27. "name":u,
  28. "numbers":list_stock_all.count(u)
  29. }
  30. insert_result = tb_result.insert_one(data_stock) #存储至mongodb中
  31. print("股票名称:" + u + " , 重复数:" + str(list_stock_all.count(u)))

这样,就将数据稍微处理了一下存入了 tb_data 的集合中;

下面只披露部分处理的数据:

  1. {'_id': ObjectId('5e0b5ecc7479db5ac2ec62c9'), 'name': '水晶光电', 'numbers': 61}
  2. {'_id': ObjectId('5e0b5ecc7479db5ac2ec62ca'), 'name': '老百姓', 'numbers': 77}
  3. {'_id': ObjectId('5e0b5ecc7479db5ac2ec62cb'), 'name': '北方华创', 'numbers': 52}
  4. {'_id': ObjectId('5e0b5ecc7479db5ac2ec62cc'), 'name': '金风科技', 'numbers': 84}
  5. {'_id': ObjectId('5e0b5ecc7479db5ac2ec62cd'), 'name': '天顺风能', 'numbers': 39}
  6. {'_id': ObjectId('5e0b5ecc7479db5ac2ec62ce'), 'name': '石大胜华', 'numbers': 13}
  7. {'_id': ObjectId('5e0b5ecc7479db5ac2ec62cf'), 'name': '国投电力', 'numbers': 55}
  8. {'_id': ObjectId('5e0b5ecc7479db5ac2ec62d0'), 'name': '中国石化', 'numbers': 99}
  9. {'_id': ObjectId('5e0b5ecc7479db5ac2ec62d1'), 'name': '中国石油', 'numbers': 54}
  10. {'_id': ObjectId('5e0b5ecc7479db5ac2ec62d2'), 'name': '中国平安', 'numbers': 1517}
  11. {'_id': ObjectId('5e0b5ecc7479db5ac2ec62d3'), 'name': '贵州茅台', 'numbers': 1573}
  12. {'_id': ObjectId('5e0b5ecc7479db5ac2ec62d4'), 'name': '招商银行', 'numbers': 910}

该数据还未做排序,排名不分先后;

上面展示的数据中:

中国石化 的numbers是54,说明在5000+家的基金中有54家买了中国石化的股票;

招商银行的numbers为910,说明在5000+家的基金中有910家基金买了招商银行的股票,已经相当高了;

......

额,好了,到此也没什么好说的了;

关于Python技术储备

学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

在这里插入图片描述

二、Python必备开发工具

三、Python视频合集

观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

四、实战案例

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

五、Python练习题

检查学习结果。

六、面试资料

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

 最后祝大家天天进步!!

上面这份完整版的Python全套学习资料已经上传至CSDN官方,朋友如果需要可以直接微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/540436
推荐阅读
相关标签
  

闽ICP备14008679号