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

本文介绍了一个针对软件测试面试的刷题小程序,包含基础题、自动化测试、大厂面试真题等内容,通过实例展示了如何使用PhantomJS和Selenium抓取基金信息并写入Excel,以及利用多进程提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2024软件测试面试刷题,这个小程序(永久刷题),靠它快速找到工作了!(刷题APP的天花板)_软件测试刷题小程序-CSDN博客文章浏览阅读3k次,点赞85次,收藏12次。你知不知道有这么一个软件测试面试的刷题小程序。里面包含了面试常问的软件测试基础题,web自动化测试、app自动化测试、接口测试、性能测试、自动化测试、安全测试及一些常问到的人力资源题目。最主要的是他还收集了像阿里、华为这样的大厂面试真题,还有互动交流板块……_软件测试刷题小程序​编辑https://blog.csdn.net/AI_Green/article/details/134931243?spm=1001.2014.3001.5502https://blog.csdn.net/AI_Green/article/details/134931243?spm=1001.2014.3001.5502​编辑https://blog.csdn.net/AI_Green/article/details/134931243?spm=1001.2014.3001.5502icon-default.png?t=N7T8https://blog.csdn.net/AI_Green/article/details/134931243?spm=1001.2014.3001.5502

功能:

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

思路:

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

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

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

图片

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

图片

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

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

图片

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

8. 再将所有信息写入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))

本文小练习爬取的数据均为公开数据,并且仅限于技术研究,不给网站造成负担。请大家在练习的时候注意合法合规!

行动吧,在路上总比一直观望的要好,未来的你肯定会感谢现在拼搏的自己!如果想学习提升找不到资料,没人答疑解惑时,请及时加入群: 759968159,里面有各种测试开发资料和技术可以一起交流哦。

最后: 下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】

软件测试面试文档

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

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值