实战+代码!Selenium + Phantom JS爬取天天基金数据

news2025/7/21 4:24:51

功能:

通过程序实现从基金列表页,获取指定页数内所有基金的近一周收益率以及每支基金的详情页链接。再进入每支基金的详情页获取其余的基金信息,将所有获取到的基金详细信息按近6月收益率倒序排列写入一个Excel表格。

思路:

  1. 通过实例化Tiantian_spider类的对象,初始化一个PhantomJS浏览器对象

  2. 使用浏览器对象访问天天基金近六月排行的页面,获取该页面的源码

  3. 从源码从获取每支基金所在的行(可以指定要获取基金的页数)

图片

  1. 从每行中获取每支基金的近1周收益率和基金详情链接

在这里插入图片描述

  1. 获取到每个基金的详情链接后,使用多进程分别进入每支基金的详情页面

  2. 进入详情页后,获取基金的相关信息,并存入列表

图片

  1. 将从所有基金的基金详情与在列表页获取的基金近1周收益率拼接后存入列表

  2. 再将所有信息写入Excel表格

图片

from selenium import webdriver
from lxml import etree
import time
from openpyxl import Workbook
import multiprocessing
import re

class Tiantian_spider():
   def __init__(self):
       self.driver = webdriver.PhantomJS()      #指定的PhantomJS浏览器创建浏览器对象
       self.html = None
       self.next_page = True
       self.fund_url_list = []


    #1 发起请求
   def parser_url(self):
       # if self.next_page :
       # 点击页面进行翻页
       # label[last()]---》定位到最后一个label,即<label value="xx">下一页</label>
       # last()是一个函数,表示取最后一个
       self.driver.find_element_by_xpath("//div[@id='pagebar']/label[last()]").click()
       time.sleep(4)  # 网页返回数据需要时间
       self.html = self.driver.page_source


   def parser_data_for_url(self):
       '''从基金列表页获取每支基金的近一周收益和详情链接'''
       # 解析字符串格式的HTML文档对象,将传进去的字符串转变成_Element对象
html = etree.HTML(self.html)
       tr_list = html.xpath("//table[@id ='dbtable']//tbody/tr")
       next_page = html.xpath("//div[@id ='pagebar']//label[last()]")
       for tr in tr_list:
           tds =tr.xpath("./td")
           # 将近一周收益和详情链接组成的元组加入fund_url_list列表
           self.fund_url_list.append((str(tds[8].text),str(tds[2].xpath("./a/@href")[0])))

       return next_page    # 返回下一页

    #翻页控制器
   def over_page(self,next_page):
       # 获取最后一页
       kw = next_page[0].xpath("./label[contains(@class,'end')]")
       # print(kw)
       # 判断是否是最后一页,如果是,则返回False,否则返回True
       flag = True if len(kw)==0 else False
       return flag

   def get_every_fund_url(self, url, page):
       # page:要获取前多少页的基金数据
       # 1 发起请求
       # 2 获取数据,解析数据
       self.driver.get(url)
       self.html = self.driver.page_source
       # 当页数不为0且还有下一页时,执行下面的操作
       while page > 0 and self.next_page:
           next_page= self.parser_data_for_url()
           # 4 翻页继续爬取
           self.next_page = self.over_page(next_page)
           # 如果不是下一页,就继续翻页
           if self.next_page:
                self.parser_url()
           page -= 1
       # 返回每支基金近一周收益和详情链接
       return self.fund_url_list


   def close_driver(self):
       self.driver.quit()


def save_data(data):

   wb = Workbook()     # 新创建一个文件
   ws = wb.active                 # 获取当前正在运行的工作表/激活工作表
    #将数据一行一行插入到工作表中
    #列表第一个元素将作为标题
   for i in data:
       ws.append(i)
   wb.save("近6月基金排名_" + time.strftime('%Y%m%d%H%M%S')+".xlsx")


# 多进程任务函数
# 获取进入基金的详情页获取详细信息
def run(url, nearly_1_week):

   driver = webdriver.PhantomJS()
   driver.get(url)    
   page_html = etree.HTML(driver.page_source)  # 获取页面源码
    #获取基金名称
    #通过xpath或者的是一个元素列表,要元素下面的子元素,需要取某个具体的元素,不能用列表取
   fund_name =page_html.xpath("//div[@class='fundDetail-tit']/div/text()")[0]
    #获取基金代码类名
   fund_code_class_name = page_html.xpath("//div[@class='fundDetail-tit']/div/span[last()]/@class")[0]
    #根据代码类名判断基金代码只有一个,还是有前后端两个
   if fund_code_class_name == "ui-num":
       fund_code = page_html.xpath("//div[@class='fundDetail-tit']/div/span[last()]/text()")[0]
   elif fund_code_class_name == "fundcodeInfo":
       fund_code_info = page_html.xpath("//div[@class='fundDetail-tit']/div/span[@class='fundcodeInfo']")[0]
       fund_code =  "前端: " +fund_code_info.xpath("./span[1]/text()")[0] + "    后端: " + fund_code_info.xpath("./span[2]/text()")[0]

    #收益和净值所在的上层div
   data_of_fund = page_html.xpath("//div[@class='dataOfFund']")[0]
    #近1月
   nearly_1_month =data_of_fund.xpath("./dl[1]/dd[2]/span[last()]/text()")[0]
    #近1年
   nearly_1_year =data_of_fund.xpath("./dl[1]/dd[3]/span[last()]/text()")[0]
    #日期
   date = data_of_fund.xpath("./dl[2]/dt/p/text()")[0]
   date = re.findall(r"(\d{4}-\d{2}-\d{2})", date)[0] ifre.findall(r"(\d{4}-\d{2}-\d{2})", date) else ""
    #单位净值
   unit_net_worth =data_of_fund.xpath("./dl[2]/dd[1]/span[1]/text()")[0]
    #日增长率
   daily_growth_rate =data_of_fund.xpath("./dl[2]/dd[1]/span[2]/text()")[0]
    #近3月
   nearly_3_month =data_of_fund.xpath("./dl[2]/dd[2]/span[last()]/text()")[0]
    #近3年
   nearly_3_year =data_of_fund.xpath("./dl[2]/dd[3]/span[last()]/text()")[0]
    #累计净值
   accumulated_net =data_of_fund.xpath("./dl[3]/dd[1]/span[1]/text()")[0]
    #近6月
   nearly_6_month =data_of_fund.xpath("./dl[3]/dd[2]/span[last()]/text()")[0]
    #基金成立日
   since_established =data_of_fund.xpath("./dl[3]/dd[3]/span[last()]/text()")[0]
    #获取基金类型,风险程度,规模等信息所在的上层vid
   fund_info_item =page_html.xpath("//div[@class='infoOfFund']")[0]
    #获取基金的类型以及风险程度
   fund_type = fund_info_item.xpath(".//tr[1]/td[1]/a/text()")[0]
   fund_risk =fund_info_item.xpath(".//tr[1]/td[1]/text()")[1].split()[-1].strip()
    #获取基金规模
    fund_scale =fund_info_item.xpath(".//tr[1]/td[2]/text()")[0].split(":")[-1]
    #获取基金经理
   fund_manager =fund_info_item.xpath(".//tr[1]/td[3]/a/text()")[0]
    #获取基金成立日
   establishment_date =fund_info_item.xpath(".//tr[2]/td[1]/text()")[0].split(":")[-1]
    #获取管理人
   administrator =fund_info_item.xpath(".//tr[2]/td[2]/a/text()")[0]
    #获取评级类名
   fund_rating_class_name =fund_info_item.xpath(".//tr[2]/td[3]/div/@class")[0]
   data_list = []
    #将每支基金的详细信息拼接成一个列表,并返回
   data_list.append(str(fund_code))
   data_list.append(str(fund_name))
   data_list.append(str(date))
   data_list.append(str(unit_net_worth))
   data_list.append(str(accumulated_net))
   data_list.append(str(daily_growth_rate))
   data_list.append(str(nearly_1_week))
   data_list.append(str(nearly_1_month))
   data_list.append(str(nearly_3_month))
   data_list.append(str(nearly_6_month))
   data_list.append(str(nearly_1_year))
   data_list.append(str(nearly_3_year))
   data_list.append(str(since_established))

    #根据评级所在divid的类名判断当前基金是几星
   if fund_rating_class_name == 'jjpj1':
       data_list.append("一星")
   elif fund_rating_class_name == "jjpj2":
       data_list.append("二星")
   elif fund_rating_class_name == "jjpj3":
       data_list.append("三星")
   elif fund_rating_class_name == "jjpj4":
       data_list.append("四星")
   elif fund_rating_class_name == "jjpj5":
       data_list.append("五星")
   else:
       data_list.append("暂无评级")

   data_list.append(fund_type + " | " + fund_risk)
   data_list.append(str(fund_scale))
   data_list.append(str(fund_manager))
   data_list.append(str(establishment_date))
   data_list.append(str(administrator))

    driver.quit()   # 关闭浏览器
   return data_list 


if __name__ == '__main__':

   start = time.time()
    #基金排行按近6月排行页面url
   url ="http://fund.eastmoney.com/data/fundranking.html#tall;c0;r;s6yzf;pn50;ddesc;qsd20200725;qed20210725;qdii;zq;gg;gzbd;gzfs;bbzt;sfbb"
   tiantian = Tiantian_spider()    # 实例化Tiantian_spider类
    #获取每个基金的近1周收益和基金详情链接
    #传入参数为排行页面url和要获取数据的总页数
    url_list = tiantian.get_every_fund_url(url,4)

    #要获取的数据,也作为保存excel的标题
   data = [["基金代码", "基金简称", "日期", "单位净值", "累计净值", "日增长率", "近一周", "近1月", "近3月", "近6月", \
       "近1年", "近3年", "成立来", "基金评级", "基金类型", "基金规模", "基金经理", "成立日", "管理人"]]

   result = []
    #multiprocessing.cpu_count():获取cpu核数
    #新建一个进程池,最大放cpu核数个进程
   pool = multiprocessing.Pool(multiprocessing.cpu_count())
   for nearly_1_week, url in url_list:
       # pool.apply_async:异步执行,10个任务同时执行
       # 通过进程池来执行并发任务
       # 进程池会自动找不同个数的进程来执行任务函数run, 将args=(url, nearly_1_week)中的url, nearly_1_week两个参数传入run函数
       # .get()表示获取任务函数的返回值,即基金的详细信息
       result.append(pool.apply_async(func=run, args=(url,nearly_1_week)).get())

   pool.close()    # 关闭进程池
   pool.join()     # 阻塞进程,所有进程池中的任务都执行完毕了,才能继续执行主进程
    #将基金列表按基金的近6月收益率倒序排列后加入data
   data.extend(sorted(result, key=lambda x:x[9], reverse=True))   
   save_data(data)
   end = time.time()
   print("耗时为:%s秒" % (end - start))

如果你不想一个人野蛮生长,找不到系统的资料,问题得不到帮助,坚持几天便放弃的感受的话,可以加入我们的QQ群:746506216,大家可以一起讨论交流,里面会有各种软件测试资料和技术交流。


资源分享

下方这份完整的软件测试视频学习教程已经上传CSDN官方认证的二维码,朋友们如果需要可以自行免费领取 【保证100%免费】

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/7854.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python-pandas用法大全

目录1 修改 DataFrame 某一列的数据类型2 读取和保存3 特定值的替换4 两个 DataFrame 的连接4.1 join4.2 某列作为拼接的依据5 删除某一列5.1 删除第n列5.2 删除特定名称列6 行、列重排6.1列重排6.2 行重排6.3 根据某一列的值排序6.4 随机打乱所有行7 修改某列的名称7.1 全局修…

m基于自适应门限软切换的3G和Wifi垂直切换算法的matlab仿真

目录 1.算法概述 2.仿真效果预览 3.核心MATLAB预览 4.完整MATLAB程序 1.算法概述 这里还是考虑位置信息和强度联合切换判决的方法&#xff0c;如果你的设备没法提供具体的位置信息的话&#xff0c;那么就把位置信息的权值设置为0。强度判决的权值设置为1即可。 需要传输的数…

外业精灵,在水土流失监测野外调查工作中的应用

常规的水土流失野外调查技术已难以满足现阶段区域水土流失监测工作的需求。 为探索高效、精准、高质量的水土流失数据采集技术&#xff0c;作者以山东沂蒙山泰山国家级重点治理区蒙阴县为例&#xff0c;以小流域或公里网格为调查单元&#xff0c;通过分析外业精灵的技术优势&a…

webpack高级配置

摇树&#xff08;tree shaking&#xff09; 我主要是想说摇树失败的原因&#xff08;tree shaking 失败的原因&#xff09;&#xff0c;先讲下摇树本身效果 什么是摇树&#xff1f; 举个例子 首先 webpack.config.js配置 const webpack require("webpack");/**…

Educational Codeforces Round 138 (Rated for Div. 2)

A&#xff1a;思维 题意&#xff1a;给一定的N*N的板子&#xff0c;里面放有一些乌鸦&#xff0c;这些乌鸦会攻击自己的所在行与所在列&#xff0c;问给定一个数量的乌鸦&#xff0c;问是否能够移动某只乌鸦&#xff0c;使得形成和平局面&#xff1f; 方法&#xff1a;我们发现…

股票涨跌量化怎样进行策略分析?

股票涨跌量化其实是通过Python调用Tushare库计算深证成指实时&#xff0c;对股票的成交量涨跌幅&#xff0c;主要是通过相关分析选择合适的成交量涨跌幅来计算的一种量化策略分析方法&#xff0c;也可以根据绘制股票的成交量涨跌幅度与当日股价的涨跌幅描绘出来。如果我们想快速…

目标检测论文解读复现之八:基于YOLOv5s的滑雪人员检测研究

前言 此前出了目标改进算法专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读最新目标检测算法论文&#xff0c…

Unity使用NaveMesh实现第一人称视角移动

系列文章目录 Navemesh寻路系列文章 文章目录 目录 系列文章目录 文章目录 前言 一、NavMeshPath是什么&#xff1f; 二、使用步骤 1.引入库 2.读入数据 总结 前言 navemesh已经大量使用到游戏中&#xff0c;但大部分寻路都是使用SetDestination函数&#xff0c;给予一个目标…

SpringBoot+Vue项目大学校园防疫与服务系统的设计与实现

文末获取源码 开发语言&#xff1a;Java 使用框架&#xff1a;spring boot 前端技术&#xff1a;JavaScript、Vue 、css3 开发工具&#xff1a;IDEA/MyEclipse/Eclipse、Visual Studio Code 数据库&#xff1a;MySQL 5.7/8.0 数据库管理工具&#xff1a;phpstudy/Navicat JDK版…

C++初阶 Vector模拟实现

q. > 作者&#xff1a;小萌新 专栏&#xff1a;C初阶 作者简介&#xff1a;大二学生 希望能和大家一起进步 本篇博客介绍&#xff1a;本篇博客会模拟Vector实现 学习目标 模拟默认函数实现模拟迭代器实现模拟容器大小相关函数模拟修改内容相关函数模拟访问容器相关函数 我…

xss挑战之旅11-19关

文章目录前言第11关&#xff1a;referer第12关&#xff1a;User-Agent第13关&#xff1a;cookie第14关&#xff1a;exif xss第15关&#xff1a;ng-include第16关第17关第18关第19关&#xff1a;flash xss前言 靶场&#xff1a;XSS挑战之旅 1-10关 11-20关 第11关&#xff1a;r…

『LeetCode|每日一题』---->颜色填充

目录 1.每日一句 2.作者简介 『LeetCode|每日一题』颜色填充 1.每日一题 2.解题思路 2.1 思路分析&#xff08;DFS&#xff09; 2.2 核心代码 2.3 完整代码 2.4 运行结果 1.每日一句 我的宇宙为你藏着无数个星球 2.作者简介 &#x1f3e1;个人主页&#xff1a;XiaoXiaoChe…

Git之路

文章目录指南介绍实战任务一&#xff1a;sb项目任务二&#xff1a;idea实战任务三&#xff1a;分支实战(待续)指南 如果你想在简历上写“会常用的Git的命令“&#xff0c;那么这篇文章值得你要看&#xff0c;那我们需要掌握什么呢&#xff1f;其实会简单的操作就行&#xff0c…

Matplotlib绘图-快速上手可视化工具

Matplotlib快速上手一、初识Matplotlib1.1 认识Matplotlib的图像结构1.2 绘制一个折线图二、给图像添加修饰2.1 自定义x的刻度2.2一图多线2.3一图绘制多个坐标系子图三、主流图形的绘制3.1绘制柱状图一、初识Matplotlib 是Python最常见的可视化工具之一 1.1 认识Matplotlib的…

csrf跨站请求伪造

文章目录csrf跨站请求伪造1、前戏2、csrf校验2.1、from表单如何符合校验2.2、ajax如何符合校验3、csrf相关装饰器FBVCBVcsrf跨站请求伪造 1、前戏 """ 钓鱼网站搭建一个跟正规网站一摸一样的界面&#xff08;中国银行&#xff09;用户进入到我们的网站&#x…

HyperLynx(三十)高速串行总线仿真(二)

高速串行总线仿真&#xff08;二&#xff09; 仿真实例 1.探索多层板中的PCI-E串行通道 2.设置叠层以减小损耗 3.分析通道的不同配置对损耗的影响 4.检测驱动端规范 5.检查接收器规范 6.通过仿真得出整个通道的驱动约束限制 1.探索多层板中的PCI-E串行通道 在本节练习中&…

人工智能学习:Microsoft COCO数据集读取(7)

Microsoft COCO&#xff08;Common Objects in Context&#xff09;是微软研发维护的一个大型的数据集。包含了30多万张图片和91个目标分类。可用于目标识别&#xff08;Object Detection&#xff09;、场景感知&#xff08;Penoptic Segmentation&#xff09;、语义分割&#…

【数据结构】——单链表

目录 1.链表 1.1 链表的概念及结构 1.2 链表的分类 1. 单向或者双向 2. 带头或者不带头 3. 循环或者非循环 1.3实现一个单链表&#xff08;无头单项非循环链表增删查改的实现&#xff09; 1.链表结构的创建 2.创建一个节点 3.创建一个链表 4.打印链表 5…

解读JVM级别本地缓存Caffeine青出于蓝的要诀 —— 缘何会更强、如何去上手

大家好&#xff0c;又见面了。 在前面的几篇文章中&#xff0c;我们一起聊了下本地缓存的动手实现、本地缓存相关的规范等&#xff0c;也聊了下Google的Guava Cache的相关原理与使用方式。比较心急的小伙伴已经坐不住了&#xff0c;提到本地缓存&#xff0c;怎么能不提一下“地…

软考 - 程序语言设计

程序设计语言基本概述 程序设计语言是为了书写计算机程序而人为设计的符号语言&#xff0c;用于对计算过程进行 描述、组织和推导。 低级语言&#xff1a;机器语言&#xff08;计算机硬件只能识别0和1的指令序列&#xff09;&#xff0c;汇编语言。 高级语言&#xff1a;功能…